diff --git a/core/share.go b/core/share.go index 83d9f7118..c6b97b245 100644 --- a/core/share.go +++ b/core/share.go @@ -102,16 +102,20 @@ func (r *shareRepositoryWrapper) Save(entity interface{}) (string, error) { switch v.(type) { case *model.Album: s.ResourceType = "album" - s.Contents = r.shareContentsFromAlbums(s.ID, s.ResourceIDs) + s.Contents = r.contentsLabelFromAlbums(s.ID, s.ResourceIDs) case *model.Playlist: s.ResourceType = "playlist" - s.Contents = r.shareContentsFromPlaylist(s.ID, s.ResourceIDs) + s.Contents = r.contentsLabelFromPlaylist(s.ID, s.ResourceIDs) case *model.MediaFile: s.ResourceType = "media_file" + s.Contents = r.contentsLabelFromMediaFiles(s.ID, s.ResourceIDs) default: log.Error(r.ctx, "Invalid Resource ID", "id", firstId) return "", model.ErrNotFound } + if len(s.Contents) > 30 { + s.Contents = s.Contents[:26] + "..." + } id, err = r.Persistable.Save(s) return id, err @@ -127,28 +131,49 @@ func (r *shareRepositoryWrapper) Update(id string, entity interface{}, _ ...stri return r.Persistable.Update(id, entity, cols...) } -func (r *shareRepositoryWrapper) shareContentsFromAlbums(shareID string, ids string) string { - all, err := r.ds.Album(r.ctx).GetAll(model.QueryOptions{Filters: squirrel.Eq{"id": ids}}) +func (r *shareRepositoryWrapper) contentsLabelFromAlbums(shareID string, ids string) string { + idList := strings.Split(ids, ",") + all, err := r.ds.Album(r.ctx).GetAll(model.QueryOptions{Filters: squirrel.Eq{"id": idList}}) if err != nil { log.Error(r.ctx, "Error retrieving album names for share", "share", shareID, err) return "" } names := slice.Map(all, func(a model.Album) string { return a.Name }) - content := strings.Join(names, ", ") - if len(content) > 30 { - content = content[:26] + "..." - } - return content + return strings.Join(names, ", ") } -func (r *shareRepositoryWrapper) shareContentsFromPlaylist(shareID string, id string) string { +func (r *shareRepositoryWrapper) contentsLabelFromPlaylist(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 + return pls.Name +} + +func (r *shareRepositoryWrapper) contentsLabelFromMediaFiles(shareID string, ids string) string { + idList := strings.Split(ids, ",") + mfs, err := r.ds.MediaFile(r.ctx).GetAll(model.QueryOptions{Filters: squirrel.Eq{"id": idList}}) + if err != nil { + log.Error(r.ctx, "Error retrieving media files for share", "share", shareID, err) + return "" + } + + albums := slice.Group(mfs, func(mf model.MediaFile) string { + return mf.Album + }) + if len(albums) == 1 { + for name := range albums { + return name + } + } + artists := slice.Group(mfs, func(mf model.MediaFile) string { + return mf.AlbumArtist + }) + if len(artists) == 1 { + for name := range artists { + return name + } + } + + return mfs[0].Title } diff --git a/server/subsonic/sharing.go b/server/subsonic/sharing.go index 4f19dec90..d52549b20 100644 --- a/server/subsonic/sharing.go +++ b/server/subsonic/sharing.go @@ -38,6 +38,9 @@ func (api *Router) buildShare(r *http.Request, share model.Share) responses.Shar LastVisited: share.LastVisitedAt, VisitCount: share.VisitCount, } + if resp.Description == "" { + resp.Description = share.Contents + } if len(share.Albums) > 0 { resp.Entry = childrenFromAlbums(r.Context(), share.Albums) } else { diff --git a/ui/src/share/ShareList.js b/ui/src/share/ShareList.js index ab90bfa69..35272e29f 100644 --- a/ui/src/share/ShareList.js +++ b/ui/src/share/ShareList.js @@ -5,12 +5,14 @@ import { NumberField, SimpleList, TextField, + useNotify, useTranslate, } from 'react-admin' import React from 'react' +import { IconButton, Link, useMediaQuery } from '@material-ui/core' +import ShareIcon from '@material-ui/icons/Share' import { DateField, QualityInfo } from '../common' import { shareUrl } from '../utils' -import { Link, useMediaQuery } from '@material-ui/core' import config from '../config' export const FormatInfo = ({ record, size }) => { @@ -23,6 +25,33 @@ export const FormatInfo = ({ record, size }) => { const ShareList = (props) => { const isXsmall = useMediaQuery((theme) => theme.breakpoints.down('xs')) const translate = useTranslate() + const notify = useNotify() + + const handleShare = (r) => (e) => { + const url = shareUrl(r?.id) + navigator.clipboard + .writeText(url) + .then(() => { + notify(translate('message.shareSuccess', { url }), { + type: 'info', + multiLine: true, + duration: 0, + }) + }) + .catch((err) => { + notify( + translate('message.shareFailure', { url }) + ': ' + err.message, + { + type: 'warning', + multiLine: true, + duration: 0, + } + ) + }) + e.preventDefault() + e.stopPropagation() + } + return ( { > {isXsmall ? ( ( + + + + )} primaryText={(r) => r.description || r.contents || r.id} secondaryText={(r) => ( <> {translate('resources.share.fields.expiresAt')}:{' '} - + )} + tertiaryText={(r) => + `${translate('resources.share.fields.visitCount')}: ${ + r.visitCount || '0' + }` + } /> ) : (