mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-08 13:00:13 +02:00
feat: "open in spotify" button (#1839)
* feat: open in spotify * fix: disable native spotify URI by default
This commit is contained in:
@@ -298,6 +298,8 @@ interface AlbumMetadataExternalLinksProps {
|
||||
lastFM: boolean;
|
||||
mbzId?: null | string;
|
||||
musicBrainz: boolean;
|
||||
nativeSpotify: boolean;
|
||||
spotify: boolean;
|
||||
}
|
||||
|
||||
const AlbumMetadataExternalLinks = ({
|
||||
@@ -307,10 +309,12 @@ const AlbumMetadataExternalLinks = ({
|
||||
lastFM,
|
||||
mbzId,
|
||||
musicBrainz,
|
||||
nativeSpotify,
|
||||
spotify,
|
||||
}: AlbumMetadataExternalLinksProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (!externalLinks || (!lastFM && !musicBrainz)) return null;
|
||||
if (!externalLinks || (!lastFM && !musicBrainz && !spotify)) return null;
|
||||
|
||||
return (
|
||||
<Stack gap="xs">
|
||||
@@ -358,6 +362,28 @@ const AlbumMetadataExternalLinks = ({
|
||||
variant="subtle"
|
||||
/>
|
||||
) : null}
|
||||
{spotify && (
|
||||
<ActionIcon
|
||||
component="a"
|
||||
href={
|
||||
nativeSpotify
|
||||
? `spotify:search:${encodeURIComponent(albumArtist || '')}%20${encodeURIComponent(albumName || '')}`
|
||||
: `https://open.spotify.com/search/${encodeURIComponent(albumArtist || '')}%20${encodeURIComponent(albumName || '')}`
|
||||
}
|
||||
icon="brandSpotify"
|
||||
iconProps={{
|
||||
fill: 'default',
|
||||
size: 'xl',
|
||||
}}
|
||||
radius="md"
|
||||
rel="noopener noreferrer"
|
||||
target={nativeSpotify ? undefined : '_blank'}
|
||||
tooltip={{
|
||||
label: t('action.openIn.spotify'),
|
||||
}}
|
||||
variant="subtle"
|
||||
/>
|
||||
)}
|
||||
</Group>
|
||||
</Stack>
|
||||
);
|
||||
@@ -370,7 +396,7 @@ export const AlbumDetailContent = () => {
|
||||
albumQueries.detail({ query: { id: albumId }, serverId: server.id }),
|
||||
);
|
||||
|
||||
const { externalLinks, lastFM, musicBrainz } = useExternalLinks();
|
||||
const { externalLinks, lastFM, musicBrainz, nativeSpotify, spotify } = useExternalLinks();
|
||||
|
||||
const comment = detailQuery?.data?.comment;
|
||||
|
||||
@@ -403,6 +429,8 @@ export const AlbumDetailContent = () => {
|
||||
lastFM={lastFM}
|
||||
mbzId={mbzId || undefined}
|
||||
musicBrainz={musicBrainz}
|
||||
nativeSpotify={nativeSpotify}
|
||||
spotify={spotify}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -890,7 +890,9 @@ interface AlbumArtistMetadataExternalLinksProps {
|
||||
lastFM: boolean;
|
||||
mbzId?: null | string;
|
||||
musicBrainz: boolean;
|
||||
nativeSpotify: boolean;
|
||||
order?: number;
|
||||
spotify: boolean;
|
||||
}
|
||||
|
||||
const AlbumArtistMetadataExternalLinks = ({
|
||||
@@ -899,11 +901,13 @@ const AlbumArtistMetadataExternalLinks = ({
|
||||
lastFM,
|
||||
mbzId,
|
||||
musicBrainz,
|
||||
nativeSpotify,
|
||||
order,
|
||||
spotify,
|
||||
}: AlbumArtistMetadataExternalLinksProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (!externalLinks || (!lastFM && !musicBrainz)) return null;
|
||||
if (!externalLinks || (!lastFM && !musicBrainz && !spotify)) return null;
|
||||
|
||||
return (
|
||||
<Grid.Col order={order} span={12}>
|
||||
@@ -948,6 +952,27 @@ const AlbumArtistMetadataExternalLinks = ({
|
||||
variant="subtle"
|
||||
/>
|
||||
) : null}
|
||||
{spotify && (
|
||||
<ActionIcon
|
||||
component="a"
|
||||
href={
|
||||
nativeSpotify
|
||||
? `spotify:search:${encodeURIComponent(artistName || '')}`
|
||||
: `https://open.spotify.com/search/${encodeURIComponent(artistName || '')}`
|
||||
}
|
||||
icon="brandSpotify"
|
||||
iconProps={{
|
||||
fill: 'default',
|
||||
size: 'xl',
|
||||
}}
|
||||
rel="noopener noreferrer"
|
||||
target={nativeSpotify ? undefined : '_blank'}
|
||||
tooltip={{
|
||||
label: t('action.openIn.spotify'),
|
||||
}}
|
||||
variant="subtle"
|
||||
/>
|
||||
)}
|
||||
</Group>
|
||||
</Stack>
|
||||
</Grid.Col>
|
||||
@@ -1050,7 +1075,7 @@ export const AlbumArtistDetailContent = ({
|
||||
}: AlbumArtistDetailContentProps) => {
|
||||
const artistItems = useArtistItems();
|
||||
const artistRadioCount = useArtistRadioCount();
|
||||
const { externalLinks, lastFM, musicBrainz } = useExternalLinks();
|
||||
const { externalLinks, lastFM, musicBrainz, nativeSpotify, spotify } = useExternalLinks();
|
||||
const { albumArtistId, artistId } = useParams() as {
|
||||
albumArtistId?: string;
|
||||
artistId?: string;
|
||||
@@ -1136,14 +1161,16 @@ export const AlbumArtistDetailContent = ({
|
||||
genres={detailQuery.data?.genres}
|
||||
order={genresOrder}
|
||||
/>
|
||||
{externalLinks && (lastFM || musicBrainz) && (
|
||||
{externalLinks && (lastFM || musicBrainz || spotify) && (
|
||||
<AlbumArtistMetadataExternalLinks
|
||||
artistName={detailQuery.data?.name}
|
||||
externalLinks={externalLinks}
|
||||
lastFM={lastFM}
|
||||
mbzId={mbzId}
|
||||
musicBrainz={musicBrainz}
|
||||
nativeSpotify={nativeSpotify}
|
||||
order={externalLinksOrder}
|
||||
spotify={spotify}
|
||||
/>
|
||||
)}
|
||||
{enabledItem.biography && (
|
||||
|
||||
@@ -601,6 +601,48 @@ export const ApplicationSettings = memo(() => {
|
||||
isHidden: !settings.externalLinks,
|
||||
title: t('setting.musicbrainz', { postProcess: 'sentenceCase' }),
|
||||
},
|
||||
{
|
||||
control: (
|
||||
<Switch
|
||||
defaultChecked={settings.spotify}
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
spotify: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
),
|
||||
description: t('setting.spotify', {
|
||||
context: 'description',
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
isHidden: !settings.externalLinks,
|
||||
title: t('setting.spotify', { postProcess: 'sentenceCase' }),
|
||||
},
|
||||
{
|
||||
control: (
|
||||
<Switch
|
||||
defaultChecked={settings.nativeSpotify}
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
nativeSpotify: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
),
|
||||
description: t('setting.nativeSpotify', {
|
||||
context: 'description',
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
isHidden: !settings.externalLinks || !settings.spotify,
|
||||
title: t('setting.nativeSpotify', { postProcess: 'sentenceCase' }),
|
||||
},
|
||||
{
|
||||
control: (
|
||||
<Switch
|
||||
|
||||
Reference in New Issue
Block a user