2023-01-22 00:49:22 -05:00
|
|
|
import { SimpleForm, useTranslate } from 'react-admin'
|
2022-12-18 12:12:37 -05:00
|
|
|
import { useDispatch, useSelector } from 'react-redux'
|
|
|
|
|
import {
|
|
|
|
|
Button,
|
|
|
|
|
Dialog,
|
|
|
|
|
DialogActions,
|
|
|
|
|
DialogContent,
|
|
|
|
|
DialogTitle,
|
|
|
|
|
} from '@material-ui/core'
|
|
|
|
|
import subsonic from '../subsonic'
|
feat(artist): add Share and Download actions to the Artist detail page (#5944)
* feat(ui): add Share button to artist detail page
* feat(ui): add Download button to artist detail page
* fix(ui): scope artist share/download to album-artist content
Gate the artist Share/Download actions on album-artist stats and show the
album-artist size, since ZipArtist and the share query only cover
album_artist_id songs. Previously the total (role-inclusive) size was shown
and guest-only artists could produce an empty archive. Applies to the artist
toolbar, the shared context menu, and the download dialog title.
* fix: match artist download/share to album-artist participation
ZipArtist and the artist share query filtered the deprecated album_artist_id
column, which only stores the first album artist of a track. Secondary
album-artists (co-credited but not first) got an empty download/share even
though the UI offered it. Filter by the album-artist role participation
instead, matching the artist's album-artist stats used to gate the actions.
Also cover the artist-specific size branch of the download dialog.
* fix(share): scope artist shares to the owner's libraries
The artist share query broadened to album-artist participation, which could
pull a secondary album artist's tracks from libraries the (non-admin) share
owner cannot access into the public share. Load the artist share as the owner
so their library access is applied, mirroring how playlist shares already work.
Adds a repository test covering co-album-artist inclusion and library scoping.
* test(share): assert album participation branch of artist shares
Link the co-album-artist fixtures to albums and assert share.Albums (used by
Subsonic getShares) includes the accessible album and excludes the one in a
library the owner cannot access, so the album participation + scoping branch
is covered too.
* fix: exclude missing files from artist download/share actions
An artist's stats still count files that went missing, so the toolbar/context
menu could offer Download/Share for an artist whose files are all gone, while
the share query (missing=false) returns nothing and downloads open dead paths.
Hide the actions when the artist is missing and exclude missing files from
ZipArtist, matching the share semantics.
* refactor: dedupe artist download-size and share-owner lookups
Extract the 'album-artist download size (or none when missing)' rule into a
single artistDownloadSize() helper shared by the toolbar, context menu, and
download dialog, and factor the duplicated share-owner context lookup into a
shareRepository.ownerContext() method used by both the artist and playlist
share cases.
* refactor(ui): move artistDownloadSize helper to common
utils is for domain-agnostic, potentially portable code; this helper is
Navidrome-specific (artist stats shape), so it belongs in common. Consumers
import it directly from common/artist to avoid pulling in the common barrel.
2026-08-12 11:59:56 -04:00
|
|
|
import { closeDownloadMenu, DOWNLOAD_MENU_ARTIST } from '../actions'
|
2022-12-18 12:12:37 -05:00
|
|
|
import { formatBytes } from '../utils'
|
feat(artist): add Share and Download actions to the Artist detail page (#5944)
* feat(ui): add Share button to artist detail page
* feat(ui): add Download button to artist detail page
* fix(ui): scope artist share/download to album-artist content
Gate the artist Share/Download actions on album-artist stats and show the
album-artist size, since ZipArtist and the share query only cover
album_artist_id songs. Previously the total (role-inclusive) size was shown
and guest-only artists could produce an empty archive. Applies to the artist
toolbar, the shared context menu, and the download dialog title.
* fix: match artist download/share to album-artist participation
ZipArtist and the artist share query filtered the deprecated album_artist_id
column, which only stores the first album artist of a track. Secondary
album-artists (co-credited but not first) got an empty download/share even
though the UI offered it. Filter by the album-artist role participation
instead, matching the artist's album-artist stats used to gate the actions.
Also cover the artist-specific size branch of the download dialog.
* fix(share): scope artist shares to the owner's libraries
The artist share query broadened to album-artist participation, which could
pull a secondary album artist's tracks from libraries the (non-admin) share
owner cannot access into the public share. Load the artist share as the owner
so their library access is applied, mirroring how playlist shares already work.
Adds a repository test covering co-album-artist inclusion and library scoping.
* test(share): assert album participation branch of artist shares
Link the co-album-artist fixtures to albums and assert share.Albums (used by
Subsonic getShares) includes the accessible album and excludes the one in a
library the owner cannot access, so the album participation + scoping branch
is covered too.
* fix: exclude missing files from artist download/share actions
An artist's stats still count files that went missing, so the toolbar/context
menu could offer Download/Share for an artist whose files are all gone, while
the share query (missing=false) returns nothing and downloads open dead paths.
Hide the actions when the artist is missing and exclude missing files from
ZipArtist, matching the share semantics.
* refactor: dedupe artist download-size and share-owner lookups
Extract the 'album-artist download size (or none when missing)' rule into a
single artistDownloadSize() helper shared by the toolbar, context menu, and
download dialog, and factor the duplicated share-owner context lookup into a
shareRepository.ownerContext() method used by both the artist and playlist
share cases.
* refactor(ui): move artistDownloadSize helper to common
utils is for domain-agnostic, potentially portable code; this helper is
Navidrome-specific (artist stats shape), so it belongs in common. Consumers
import it directly from common/artist to avoid pulling in the common barrel.
2026-08-12 11:59:56 -04:00
|
|
|
import { artistDownloadSize } from '../common/artist'
|
2023-01-22 00:49:22 -05:00
|
|
|
import { useTranscodingOptions } from './useTranscodingOptions'
|
2022-12-18 12:12:37 -05:00
|
|
|
|
|
|
|
|
const DownloadMenuDialog = () => {
|
|
|
|
|
const { open, record, recordType } = useSelector(
|
2023-12-18 14:56:03 -05:00
|
|
|
(state) => state.downloadMenuDialog,
|
2022-12-18 12:12:37 -05:00
|
|
|
)
|
|
|
|
|
const dispatch = useDispatch()
|
|
|
|
|
const translate = useTranslate()
|
|
|
|
|
|
2023-01-22 00:49:22 -05:00
|
|
|
const { TranscodingOptionsInput, format, maxBitRate, originalFormat } =
|
|
|
|
|
useTranscodingOptions()
|
2022-12-18 12:12:37 -05:00
|
|
|
|
feat(artist): add Share and Download actions to the Artist detail page (#5944)
* feat(ui): add Share button to artist detail page
* feat(ui): add Download button to artist detail page
* fix(ui): scope artist share/download to album-artist content
Gate the artist Share/Download actions on album-artist stats and show the
album-artist size, since ZipArtist and the share query only cover
album_artist_id songs. Previously the total (role-inclusive) size was shown
and guest-only artists could produce an empty archive. Applies to the artist
toolbar, the shared context menu, and the download dialog title.
* fix: match artist download/share to album-artist participation
ZipArtist and the artist share query filtered the deprecated album_artist_id
column, which only stores the first album artist of a track. Secondary
album-artists (co-credited but not first) got an empty download/share even
though the UI offered it. Filter by the album-artist role participation
instead, matching the artist's album-artist stats used to gate the actions.
Also cover the artist-specific size branch of the download dialog.
* fix(share): scope artist shares to the owner's libraries
The artist share query broadened to album-artist participation, which could
pull a secondary album artist's tracks from libraries the (non-admin) share
owner cannot access into the public share. Load the artist share as the owner
so their library access is applied, mirroring how playlist shares already work.
Adds a repository test covering co-album-artist inclusion and library scoping.
* test(share): assert album participation branch of artist shares
Link the co-album-artist fixtures to albums and assert share.Albums (used by
Subsonic getShares) includes the accessible album and excludes the one in a
library the owner cannot access, so the album participation + scoping branch
is covered too.
* fix: exclude missing files from artist download/share actions
An artist's stats still count files that went missing, so the toolbar/context
menu could offer Download/Share for an artist whose files are all gone, while
the share query (missing=false) returns nothing and downloads open dead paths.
Hide the actions when the artist is missing and exclude missing files from
ZipArtist, matching the share semantics.
* refactor: dedupe artist download-size and share-owner lookups
Extract the 'album-artist download size (or none when missing)' rule into a
single artistDownloadSize() helper shared by the toolbar, context menu, and
download dialog, and factor the duplicated share-owner context lookup into a
shareRepository.ownerContext() method used by both the artist and playlist
share cases.
* refactor(ui): move artistDownloadSize helper to common
utils is for domain-agnostic, potentially portable code; this helper is
Navidrome-specific (artist stats shape), so it belongs in common. Consumers
import it directly from common/artist to avoid pulling in the common barrel.
2026-08-12 11:59:56 -04:00
|
|
|
// Artist downloads only include album-artist songs, so show that size
|
|
|
|
|
const downloadSize =
|
|
|
|
|
recordType === DOWNLOAD_MENU_ARTIST
|
|
|
|
|
? artistDownloadSize(record)
|
|
|
|
|
: record?.size
|
|
|
|
|
|
2022-12-18 12:12:37 -05:00
|
|
|
const handleClose = (e) => {
|
|
|
|
|
dispatch(closeDownloadMenu())
|
|
|
|
|
e.stopPropagation()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleDownload = (e) => {
|
|
|
|
|
if (record) {
|
2023-01-30 11:20:22 -05:00
|
|
|
const id = record.mediaFileId || record.id
|
2023-01-22 00:49:22 -05:00
|
|
|
if (originalFormat) {
|
2023-01-30 11:20:22 -05:00
|
|
|
subsonic.download(id, 'raw')
|
2023-01-22 00:49:22 -05:00
|
|
|
} else {
|
2023-01-30 11:20:22 -05:00
|
|
|
subsonic.download(id, format, maxBitRate?.toString())
|
2023-01-22 00:49:22 -05:00
|
|
|
}
|
2022-12-18 12:12:37 -05:00
|
|
|
dispatch(closeDownloadMenu())
|
|
|
|
|
}
|
|
|
|
|
e.stopPropagation()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
2023-01-22 00:49:22 -05:00
|
|
|
<Dialog
|
|
|
|
|
open={open}
|
|
|
|
|
onClose={handleClose}
|
|
|
|
|
aria-labelledby="download-dialog"
|
|
|
|
|
fullWidth={true}
|
|
|
|
|
maxWidth={'sm'}
|
|
|
|
|
>
|
|
|
|
|
<DialogTitle id="download-dialog">
|
2023-01-23 10:25:06 -05:00
|
|
|
{recordType &&
|
|
|
|
|
translate('message.downloadDialogTitle', {
|
|
|
|
|
resource: translate(`resources.${recordType}.name`, {
|
|
|
|
|
smart_count: 1,
|
|
|
|
|
}).toLocaleLowerCase(),
|
|
|
|
|
name: record?.name || record?.title,
|
feat(artist): add Share and Download actions to the Artist detail page (#5944)
* feat(ui): add Share button to artist detail page
* feat(ui): add Download button to artist detail page
* fix(ui): scope artist share/download to album-artist content
Gate the artist Share/Download actions on album-artist stats and show the
album-artist size, since ZipArtist and the share query only cover
album_artist_id songs. Previously the total (role-inclusive) size was shown
and guest-only artists could produce an empty archive. Applies to the artist
toolbar, the shared context menu, and the download dialog title.
* fix: match artist download/share to album-artist participation
ZipArtist and the artist share query filtered the deprecated album_artist_id
column, which only stores the first album artist of a track. Secondary
album-artists (co-credited but not first) got an empty download/share even
though the UI offered it. Filter by the album-artist role participation
instead, matching the artist's album-artist stats used to gate the actions.
Also cover the artist-specific size branch of the download dialog.
* fix(share): scope artist shares to the owner's libraries
The artist share query broadened to album-artist participation, which could
pull a secondary album artist's tracks from libraries the (non-admin) share
owner cannot access into the public share. Load the artist share as the owner
so their library access is applied, mirroring how playlist shares already work.
Adds a repository test covering co-album-artist inclusion and library scoping.
* test(share): assert album participation branch of artist shares
Link the co-album-artist fixtures to albums and assert share.Albums (used by
Subsonic getShares) includes the accessible album and excludes the one in a
library the owner cannot access, so the album participation + scoping branch
is covered too.
* fix: exclude missing files from artist download/share actions
An artist's stats still count files that went missing, so the toolbar/context
menu could offer Download/Share for an artist whose files are all gone, while
the share query (missing=false) returns nothing and downloads open dead paths.
Hide the actions when the artist is missing and exclude missing files from
ZipArtist, matching the share semantics.
* refactor: dedupe artist download-size and share-owner lookups
Extract the 'album-artist download size (or none when missing)' rule into a
single artistDownloadSize() helper shared by the toolbar, context menu, and
download dialog, and factor the duplicated share-owner context lookup into a
shareRepository.ownerContext() method used by both the artist and playlist
share cases.
* refactor(ui): move artistDownloadSize helper to common
utils is for domain-agnostic, potentially portable code; this helper is
Navidrome-specific (artist stats shape), so it belongs in common. Consumers
import it directly from common/artist to avoid pulling in the common barrel.
2026-08-12 11:59:56 -04:00
|
|
|
size: formatBytes(downloadSize),
|
2023-01-23 10:25:06 -05:00
|
|
|
})}
|
2023-01-22 00:49:22 -05:00
|
|
|
</DialogTitle>
|
|
|
|
|
<DialogContent>
|
|
|
|
|
<SimpleForm toolbar={null} variant={'outlined'}>
|
|
|
|
|
<TranscodingOptionsInput
|
|
|
|
|
fullWidth
|
2023-01-24 20:14:05 -05:00
|
|
|
label={translate('message.downloadOriginalFormat')}
|
2023-01-22 00:49:22 -05:00
|
|
|
/>
|
|
|
|
|
</SimpleForm>
|
|
|
|
|
</DialogContent>
|
|
|
|
|
<DialogActions>
|
|
|
|
|
<Button onClick={handleClose} color="secondary">
|
|
|
|
|
{translate('ra.action.close')}
|
|
|
|
|
</Button>
|
2023-01-24 13:04:00 -05:00
|
|
|
<Button onClick={handleDownload} color="primary">
|
|
|
|
|
{translate('ra.action.download')}
|
|
|
|
|
</Button>
|
2023-01-22 00:49:22 -05:00
|
|
|
</DialogActions>
|
|
|
|
|
</Dialog>
|
2022-12-18 12:12:37 -05:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default DownloadMenuDialog
|