mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-06 20:10:12 +02:00
add qobuz and listenbrainz external links
This commit is contained in:
@@ -29,12 +29,14 @@ These variables override app settings **on first run** when no persisted setting
|
||||
| `general.themeLight` | `defaultLight` | `FS_GENERAL_THEME_LIGHT` | Same as theme (used when system is light). |
|
||||
| `general.lastfmApiKey` | *(empty)* | `FS_GENERAL_LASTFM_API_KEY` | Last.fm API key. |
|
||||
| `general.lastFM` | `true` | `FS_GENERAL_LAST_FM` | `true` / `false` — Enable Last.fm. |
|
||||
| `general.listenBrainz` | `true` | `FS_GENERAL_LISTEN_BRAINZ` | `true` / `false` — ListenBrainz links. |
|
||||
| `general.musicBrainz` | `true` | `FS_GENERAL_MUSIC_BRAINZ` | `true` / `false` — MusicBrainz links. |
|
||||
| `general.nativeAspectRatio` | `false` | `FS_GENERAL_NATIVE_ASPECT_RATIO` | `true` / `false` — Use native cover art aspect ratio. |
|
||||
| `general.pathReplace` | *(empty)* | `FS_GENERAL_PATH_REPLACE` | Path pattern to replace (e.g. server path in Docker). |
|
||||
| `general.pathReplaceWith` | *(empty)* | `FS_GENERAL_PATH_REPLACE_WITH` | Replacement path. |
|
||||
| `general.playerbarOpenDrawer` | `false` | `FS_GENERAL_PLAYERBAR_OPEN_DRAWER` | `true` / `false` — Open queue/lyrics as drawer from player bar. |
|
||||
| `general.primaryShade` | `6` | `FS_GENERAL_PRIMARY_SHADE` | Mantine primary shade 0–9 (number). |
|
||||
| `general.qobuz` | `true` | `FS_GENERAL_QOBUZ` | `true` / `false` — Qobuz links. |
|
||||
| `general.resume` | `true` | `FS_GENERAL_RESUME` | `true` / `false` — Resume playback on load. |
|
||||
| `general.showLyricsInSidebar` | `true` | `FS_GENERAL_SHOW_LYRICS_IN_SIDEBAR` | `true` / `false` — Show lyrics in sidebar. |
|
||||
| `general.showRatings` | `true` | `FS_GENERAL_SHOW_RATINGS` | `true` / `false` — Show star ratings. |
|
||||
|
||||
@@ -24,12 +24,14 @@ window.FS_GENERAL_HOME_FEATURE_STYLE = "${FS_GENERAL_HOME_FEATURE_STYLE}";
|
||||
window.FS_GENERAL_LANGUAGE = "${FS_GENERAL_LANGUAGE}";
|
||||
window.FS_GENERAL_LAST_FM = "${FS_GENERAL_LAST_FM}";
|
||||
window.FS_GENERAL_LASTFM_API_KEY = "${FS_GENERAL_LASTFM_API_KEY}";
|
||||
window.FS_GENERAL_LISTEN_BRAINZ = "${FS_GENERAL_LISTEN_BRAINZ}";
|
||||
window.FS_GENERAL_MUSIC_BRAINZ = "${FS_GENERAL_MUSIC_BRAINZ}";
|
||||
window.FS_GENERAL_NATIVE_ASPECT_RATIO = "${FS_GENERAL_NATIVE_ASPECT_RATIO}";
|
||||
window.FS_GENERAL_PATH_REPLACE = "${FS_GENERAL_PATH_REPLACE}";
|
||||
window.FS_GENERAL_PATH_REPLACE_WITH = "${FS_GENERAL_PATH_REPLACE_WITH}";
|
||||
window.FS_GENERAL_PLAYERBAR_OPEN_DRAWER = "${FS_GENERAL_PLAYERBAR_OPEN_DRAWER}";
|
||||
window.FS_GENERAL_PRIMARY_SHADE = "${FS_GENERAL_PRIMARY_SHADE}";
|
||||
window.FS_GENERAL_QOBUZ = "${FS_GENERAL_QOBUZ}";
|
||||
window.FS_GENERAL_RESUME = "${FS_GENERAL_RESUME}";
|
||||
window.FS_GENERAL_SHOW_LYRICS_IN_SIDEBAR = "${FS_GENERAL_SHOW_LYRICS_IN_SIDEBAR}";
|
||||
window.FS_GENERAL_SHOW_RATINGS = "${FS_GENERAL_SHOW_RATINGS}";
|
||||
|
||||
@@ -37,7 +37,9 @@
|
||||
"openApplicationDirectory": "open application directory",
|
||||
"openIn": {
|
||||
"lastfm": "Open in Last.fm",
|
||||
"listenbrainz": "Open in ListenBrainz",
|
||||
"musicbrainz": "Open in MusicBrainz",
|
||||
"qobuz": "Open in Qobuz",
|
||||
"spotify": "Open in Spotify"
|
||||
}
|
||||
},
|
||||
@@ -898,6 +900,8 @@
|
||||
"language_description": "sets the language for the application ($t(common.restartRequired))",
|
||||
"lastfm_description": "show links to Last.fm on artist/album pages",
|
||||
"lastfm": "show last.fm links",
|
||||
"listenbrainz_description": "show links to ListenBrainz on artist/album pages",
|
||||
"listenbrainz": "show ListenBrainz links",
|
||||
"lastfmApiKey_description": "the API key for {{lastfm}}. required for cover art",
|
||||
"lastfmApiKey": "{{lastfm}} API key",
|
||||
"lyricFetch_description": "fetch lyrics from various internet sources",
|
||||
@@ -925,6 +929,8 @@
|
||||
"mpvExtraParameters_help": "one per line",
|
||||
"musicbrainz_description": "show links to MusicBrainz on artist/album pages, where MusicBrainz ID exists",
|
||||
"musicbrainz": "show MusicBrainz links",
|
||||
"qobuz_description": "show links to Qobuz on artist/album pages",
|
||||
"qobuz": "show Qobuz links",
|
||||
"spotify_description": "show links to Spotify on artist/album pages",
|
||||
"spotify": "show Spotify links",
|
||||
"nativeSpotify_description": "open in the Spotify app instead of your browser",
|
||||
|
||||
@@ -296,25 +296,60 @@ interface AlbumMetadataExternalLinksProps {
|
||||
albumName?: string;
|
||||
externalLinks: boolean;
|
||||
lastFM: boolean;
|
||||
listenBrainz: boolean;
|
||||
mbzId?: null | string;
|
||||
mbzReleaseGroupId?: null | string;
|
||||
musicBrainz: boolean;
|
||||
nativeSpotify: boolean;
|
||||
qobuz: boolean;
|
||||
spotify: boolean;
|
||||
}
|
||||
|
||||
const getListenBrainzUrl = (
|
||||
mbzReleaseGroupId: null | string,
|
||||
albumArtist?: string,
|
||||
albumName?: string,
|
||||
) => {
|
||||
if (mbzReleaseGroupId) {
|
||||
return `https://listenbrainz.org/album/${mbzReleaseGroupId}`;
|
||||
}
|
||||
|
||||
if (albumArtist || albumName) {
|
||||
return `https://listenbrainz.org/search/?search_term=${encodeURIComponent([albumArtist, albumName].filter(Boolean).join(' ').trim())}`;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const getQobuzUrl = (albumArtist?: string, albumName?: string) => {
|
||||
if (albumArtist || albumName) {
|
||||
return `https://www.qobuz.com/us-en/search/albums/${encodeURIComponent([albumArtist, albumName].filter(Boolean).join(' ').trim())}`;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const AlbumMetadataExternalLinks = ({
|
||||
albumArtist,
|
||||
albumName,
|
||||
externalLinks,
|
||||
lastFM,
|
||||
listenBrainz,
|
||||
mbzId,
|
||||
mbzReleaseGroupId,
|
||||
musicBrainz,
|
||||
nativeSpotify,
|
||||
qobuz,
|
||||
spotify,
|
||||
}: AlbumMetadataExternalLinksProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (!externalLinks || (!lastFM && !musicBrainz && !spotify)) return null;
|
||||
const listenBrainzUrl = getListenBrainzUrl(mbzReleaseGroupId || null, albumArtist, albumName);
|
||||
const qobuzUrl = getQobuzUrl(albumArtist, albumName);
|
||||
|
||||
if (!externalLinks || (!lastFM && !listenBrainz && !musicBrainz && !qobuz && !spotify)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack gap="xs">
|
||||
@@ -323,7 +358,7 @@ const AlbumMetadataExternalLinks = ({
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
</Text>
|
||||
<Group className={styles.externalLinksGroup} gap="sm">
|
||||
<Group className={styles.externalLinksGroup} gap="xs">
|
||||
{lastFM && (
|
||||
<ActionIcon
|
||||
component="a"
|
||||
@@ -332,8 +367,7 @@ const AlbumMetadataExternalLinks = ({
|
||||
)}/${encodeURIComponent(albumName || '')}`}
|
||||
icon="brandLastfm"
|
||||
iconProps={{
|
||||
fill: 'default',
|
||||
size: 'xl',
|
||||
size: '2xl',
|
||||
}}
|
||||
radius="md"
|
||||
rel="noopener noreferrer"
|
||||
@@ -350,8 +384,7 @@ const AlbumMetadataExternalLinks = ({
|
||||
href={`https://musicbrainz.org/release/${mbzId}`}
|
||||
icon="brandMusicBrainz"
|
||||
iconProps={{
|
||||
fill: 'default',
|
||||
size: 'xl',
|
||||
size: '2xl',
|
||||
}}
|
||||
radius="md"
|
||||
rel="noopener noreferrer"
|
||||
@@ -362,6 +395,40 @@ const AlbumMetadataExternalLinks = ({
|
||||
variant="subtle"
|
||||
/>
|
||||
) : null}
|
||||
{listenBrainz && listenBrainzUrl && (
|
||||
<ActionIcon
|
||||
component="a"
|
||||
href={listenBrainzUrl}
|
||||
icon="brandListenBrainz"
|
||||
iconProps={{
|
||||
size: '2xl',
|
||||
}}
|
||||
radius="md"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
tooltip={{
|
||||
label: t('action.openIn.listenbrainz'),
|
||||
}}
|
||||
variant="subtle"
|
||||
/>
|
||||
)}
|
||||
{qobuz && qobuzUrl && (
|
||||
<ActionIcon
|
||||
component="a"
|
||||
href={qobuzUrl}
|
||||
icon="brandQobuz"
|
||||
iconProps={{
|
||||
size: '2xl',
|
||||
}}
|
||||
radius="md"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
tooltip={{
|
||||
label: t('action.openIn.qobuz'),
|
||||
}}
|
||||
variant="subtle"
|
||||
/>
|
||||
)}
|
||||
{spotify && (
|
||||
<ActionIcon
|
||||
component="a"
|
||||
@@ -372,8 +439,7 @@ const AlbumMetadataExternalLinks = ({
|
||||
}
|
||||
icon="brandSpotify"
|
||||
iconProps={{
|
||||
fill: 'default',
|
||||
size: 'xl',
|
||||
size: '2xl',
|
||||
}}
|
||||
radius="md"
|
||||
rel="noopener noreferrer"
|
||||
@@ -396,7 +462,8 @@ export const AlbumDetailContent = () => {
|
||||
albumQueries.detail({ query: { id: albumId }, serverId: server.id }),
|
||||
);
|
||||
|
||||
const { externalLinks, lastFM, musicBrainz, nativeSpotify, spotify } = useExternalLinks();
|
||||
const { externalLinks, lastFM, listenBrainz, musicBrainz, nativeSpotify, qobuz, spotify } =
|
||||
useExternalLinks();
|
||||
|
||||
const comment = detailQuery?.data?.comment;
|
||||
|
||||
@@ -427,9 +494,12 @@ export const AlbumDetailContent = () => {
|
||||
albumName={detailQuery?.data?.name}
|
||||
externalLinks={externalLinks}
|
||||
lastFM={lastFM}
|
||||
listenBrainz={listenBrainz}
|
||||
mbzId={mbzId || undefined}
|
||||
mbzReleaseGroupId={detailQuery?.data?.mbzReleaseGroupId}
|
||||
musicBrainz={musicBrainz}
|
||||
nativeSpotify={nativeSpotify}
|
||||
qobuz={qobuz}
|
||||
spotify={spotify}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -888,26 +888,54 @@ interface AlbumArtistMetadataExternalLinksProps {
|
||||
artistName?: string;
|
||||
externalLinks: boolean;
|
||||
lastFM: boolean;
|
||||
listenBrainz: boolean;
|
||||
mbzId?: null | string;
|
||||
musicBrainz: boolean;
|
||||
nativeSpotify: boolean;
|
||||
order?: number;
|
||||
qobuz: boolean;
|
||||
spotify: boolean;
|
||||
}
|
||||
|
||||
const getListenBrainzUrl = (mbzId: null | string, artistName?: string) => {
|
||||
if (mbzId) {
|
||||
return `https://listenbrainz.org/artist/${mbzId}`;
|
||||
}
|
||||
|
||||
if (artistName) {
|
||||
return `https://listenbrainz.org/search/?search_term=${encodeURIComponent(artistName)}`;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const getQobuzUrl = (artistName?: string) => {
|
||||
if (artistName) {
|
||||
return `https://www.qobuz.com/us-en/search/artists/${encodeURIComponent(artistName)}`;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const AlbumArtistMetadataExternalLinks = ({
|
||||
artistName,
|
||||
externalLinks,
|
||||
lastFM,
|
||||
listenBrainz,
|
||||
mbzId,
|
||||
musicBrainz,
|
||||
nativeSpotify,
|
||||
order,
|
||||
qobuz,
|
||||
spotify,
|
||||
}: AlbumArtistMetadataExternalLinksProps) => {
|
||||
const { t } = useTranslation();
|
||||
const listenBrainzUrl = getListenBrainzUrl(mbzId || null, artistName);
|
||||
const qobuzUrl = getQobuzUrl(artistName);
|
||||
|
||||
if (!externalLinks || (!lastFM && !musicBrainz && !spotify)) return null;
|
||||
if (!externalLinks || (!lastFM && !listenBrainz && !musicBrainz && !qobuz && !spotify)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Grid.Col order={order} span={12}>
|
||||
@@ -917,15 +945,14 @@ const AlbumArtistMetadataExternalLinks = ({
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
</Text>
|
||||
<Group gap="sm">
|
||||
<Group gap="xs">
|
||||
{lastFM && (
|
||||
<ActionIcon
|
||||
component="a"
|
||||
href={`https://www.last.fm/music/${encodeURIComponent(artistName || '')}`}
|
||||
icon="brandLastfm"
|
||||
iconProps={{
|
||||
fill: 'default',
|
||||
size: 'xl',
|
||||
size: '2xl',
|
||||
}}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
@@ -941,8 +968,7 @@ const AlbumArtistMetadataExternalLinks = ({
|
||||
href={`https://musicbrainz.org/artist/${mbzId}`}
|
||||
icon="brandMusicBrainz"
|
||||
iconProps={{
|
||||
fill: 'default',
|
||||
size: 'xl',
|
||||
size: '2xl',
|
||||
}}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
@@ -952,6 +978,38 @@ const AlbumArtistMetadataExternalLinks = ({
|
||||
variant="subtle"
|
||||
/>
|
||||
) : null}
|
||||
{listenBrainz && listenBrainzUrl && (
|
||||
<ActionIcon
|
||||
component="a"
|
||||
href={listenBrainzUrl}
|
||||
icon="brandListenBrainz"
|
||||
iconProps={{
|
||||
size: '2xl',
|
||||
}}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
tooltip={{
|
||||
label: t('action.openIn.listenbrainz'),
|
||||
}}
|
||||
variant="subtle"
|
||||
/>
|
||||
)}
|
||||
{qobuz && qobuzUrl && (
|
||||
<ActionIcon
|
||||
component="a"
|
||||
href={qobuzUrl}
|
||||
icon="brandQobuz"
|
||||
iconProps={{
|
||||
size: '2xl',
|
||||
}}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
tooltip={{
|
||||
label: t('action.openIn.qobuz'),
|
||||
}}
|
||||
variant="subtle"
|
||||
/>
|
||||
)}
|
||||
{spotify && (
|
||||
<ActionIcon
|
||||
component="a"
|
||||
@@ -962,8 +1020,7 @@ const AlbumArtistMetadataExternalLinks = ({
|
||||
}
|
||||
icon="brandSpotify"
|
||||
iconProps={{
|
||||
fill: 'default',
|
||||
size: 'xl',
|
||||
size: '2xl',
|
||||
}}
|
||||
rel="noopener noreferrer"
|
||||
target={nativeSpotify ? undefined : '_blank'}
|
||||
@@ -1075,7 +1132,8 @@ export const AlbumArtistDetailContent = ({
|
||||
}: AlbumArtistDetailContentProps) => {
|
||||
const artistItems = useArtistItems();
|
||||
const artistRadioCount = useArtistRadioCount();
|
||||
const { externalLinks, lastFM, musicBrainz, nativeSpotify, spotify } = useExternalLinks();
|
||||
const { externalLinks, lastFM, listenBrainz, musicBrainz, nativeSpotify, qobuz, spotify } =
|
||||
useExternalLinks();
|
||||
const { albumArtistId, artistId } = useParams() as {
|
||||
albumArtistId?: string;
|
||||
artistId?: string;
|
||||
@@ -1161,18 +1219,21 @@ export const AlbumArtistDetailContent = ({
|
||||
genres={detailQuery.data?.genres}
|
||||
order={genresOrder}
|
||||
/>
|
||||
{externalLinks && (lastFM || musicBrainz || spotify) && (
|
||||
<AlbumArtistMetadataExternalLinks
|
||||
artistName={detailQuery.data?.name}
|
||||
externalLinks={externalLinks}
|
||||
lastFM={lastFM}
|
||||
mbzId={mbzId}
|
||||
musicBrainz={musicBrainz}
|
||||
nativeSpotify={nativeSpotify}
|
||||
order={externalLinksOrder}
|
||||
spotify={spotify}
|
||||
/>
|
||||
)}
|
||||
{externalLinks &&
|
||||
(lastFM || listenBrainz || musicBrainz || qobuz || spotify) && (
|
||||
<AlbumArtistMetadataExternalLinks
|
||||
artistName={detailQuery.data?.name}
|
||||
externalLinks={externalLinks}
|
||||
lastFM={lastFM}
|
||||
listenBrainz={listenBrainz}
|
||||
mbzId={mbzId}
|
||||
musicBrainz={musicBrainz}
|
||||
nativeSpotify={nativeSpotify}
|
||||
order={externalLinksOrder}
|
||||
qobuz={qobuz}
|
||||
spotify={spotify}
|
||||
/>
|
||||
)}
|
||||
{enabledItem.biography && (
|
||||
<AlbumArtistMetadataBiography
|
||||
artistName={detailQuery.data?.name}
|
||||
|
||||
@@ -580,110 +580,6 @@ export const ApplicationSettings = memo(() => {
|
||||
isHidden: settings.sideQueueType !== 'sideQueue',
|
||||
title: t('setting.sidePlayQueueLayout', { postProcess: 'sentenceCase' }),
|
||||
},
|
||||
{
|
||||
control: (
|
||||
<Switch
|
||||
defaultChecked={settings.externalLinks}
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
externalLinks: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
),
|
||||
description: t('setting.externalLinks', {
|
||||
context: 'description',
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
title: t('setting.externalLinks', { postProcess: 'sentenceCase' }),
|
||||
},
|
||||
{
|
||||
control: (
|
||||
<Switch
|
||||
defaultChecked={settings.lastFM}
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
lastFM: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
),
|
||||
description: t('setting.lastfm', {
|
||||
context: 'description',
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
isHidden: !settings.externalLinks,
|
||||
title: t('setting.lastfm', { postProcess: 'sentenceCase' }),
|
||||
},
|
||||
{
|
||||
control: (
|
||||
<Switch
|
||||
defaultChecked={settings.musicBrainz}
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
musicBrainz: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
),
|
||||
description: t('setting.musicbrainz', {
|
||||
context: 'description',
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
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
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import {
|
||||
SettingOption,
|
||||
SettingsSection,
|
||||
} from '/@/renderer/features/settings/components/settings-section';
|
||||
import { useGeneralSettings, useSettingsStoreActions } from '/@/renderer/store/settings.store';
|
||||
import { Switch } from '/@/shared/components/switch/switch';
|
||||
|
||||
export const ExternalLinksSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const settings = useGeneralSettings();
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
|
||||
const options: SettingOption[] = [
|
||||
{
|
||||
control: (
|
||||
<Switch
|
||||
defaultChecked={settings.externalLinks}
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
externalLinks: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
),
|
||||
description: t('setting.externalLinks', {
|
||||
context: 'description',
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
title: t('setting.externalLinks', { postProcess: 'sentenceCase' }),
|
||||
},
|
||||
{
|
||||
control: (
|
||||
<Switch
|
||||
defaultChecked={settings.lastFM}
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
lastFM: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
),
|
||||
description: t('setting.lastfm', {
|
||||
context: 'description',
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
isHidden: !settings.externalLinks,
|
||||
title: t('setting.lastfm', { postProcess: 'sentenceCase' }),
|
||||
},
|
||||
{
|
||||
control: (
|
||||
<Switch
|
||||
defaultChecked={settings.listenBrainz}
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
listenBrainz: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
),
|
||||
description: t('setting.listenbrainz', {
|
||||
context: 'description',
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
isHidden: !settings.externalLinks,
|
||||
title: t('setting.listenbrainz', { postProcess: 'sentenceCase' }),
|
||||
},
|
||||
{
|
||||
control: (
|
||||
<Switch
|
||||
defaultChecked={settings.musicBrainz}
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
musicBrainz: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
),
|
||||
description: t('setting.musicbrainz', {
|
||||
context: 'description',
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
isHidden: !settings.externalLinks,
|
||||
title: t('setting.musicbrainz', { postProcess: 'sentenceCase' }),
|
||||
},
|
||||
{
|
||||
control: (
|
||||
<Switch
|
||||
defaultChecked={settings.qobuz}
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
qobuz: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
),
|
||||
description: t('setting.qobuz', {
|
||||
context: 'description',
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
isHidden: !settings.externalLinks,
|
||||
title: t('setting.qobuz', { 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' }),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<SettingsSection
|
||||
options={options}
|
||||
title={t('common.externalLinks', { postProcess: 'sentenceCase' })}
|
||||
/>
|
||||
);
|
||||
});
|
||||
@@ -3,6 +3,7 @@ import { Fragment } from 'react/jsx-runtime';
|
||||
|
||||
import { ApplicationSettings } from '/@/renderer/features/settings/components/general/application-settings';
|
||||
import { ControlSettings } from '/@/renderer/features/settings/components/general/control-settings';
|
||||
import { ExternalLinksSettings } from '/@/renderer/features/settings/components/general/external-links-settings';
|
||||
import { LyricSettings } from '/@/renderer/features/settings/components/general/lyric-settings';
|
||||
import { QueryBuilderSettings } from '/@/renderer/features/settings/components/general/query-builder-settings';
|
||||
import { ScrobbleSettings } from '/@/renderer/features/settings/components/general/scrobble-settings';
|
||||
@@ -22,6 +23,7 @@ export const GeneralTab = memo(() => {
|
||||
const baseSections = [
|
||||
{ component: ThemeSettings, key: 'theme' },
|
||||
{ component: ApplicationSettings, key: 'application' },
|
||||
{ component: ExternalLinksSettings, key: 'externalLinks' },
|
||||
{ component: ControlSettings, key: 'control' },
|
||||
{ component: SidebarSettings, key: 'sidebar' },
|
||||
{ component: ScrobbleSettings, key: 'scrobble' },
|
||||
|
||||
@@ -154,7 +154,9 @@ const ENV_SETTING_SPECS: EnvSettingSpec[] = [
|
||||
{ key: 'FS_GENERAL_PATH_REPLACE_WITH', path: ['general', 'pathReplaceWith'], type: 'string' },
|
||||
{ key: 'FS_GENERAL_LASTFM_API_KEY', path: ['general', 'lastfmApiKey'], type: 'string' },
|
||||
{ key: 'FS_GENERAL_LAST_FM', path: ['general', 'lastFM'], type: 'bool' },
|
||||
{ key: 'FS_GENERAL_LISTEN_BRAINZ', path: ['general', 'listenBrainz'], type: 'bool' },
|
||||
{ key: 'FS_GENERAL_MUSIC_BRAINZ', path: ['general', 'musicBrainz'], type: 'bool' },
|
||||
{ key: 'FS_GENERAL_QOBUZ', path: ['general', 'qobuz'], type: 'bool' },
|
||||
{ key: 'FS_GENERAL_SPOTIFY', path: ['general', 'spotify'], type: 'bool' },
|
||||
{ key: 'FS_GENERAL_SPOTIFY_NATIVE_APP', path: ['general', 'nativeSpotify'], type: 'bool' },
|
||||
{ key: 'FS_GENERAL_NATIVE_ASPECT_RATIO', path: ['general', 'nativeAspectRatio'], type: 'bool' },
|
||||
|
||||
@@ -476,6 +476,7 @@ export const GeneralSettingsSchema = z.object({
|
||||
language: z.string(),
|
||||
lastFM: z.boolean(),
|
||||
lastfmApiKey: z.string(),
|
||||
listenBrainz: z.boolean(),
|
||||
musicBrainz: z.boolean(),
|
||||
nativeAspectRatio: z.boolean(),
|
||||
nativeSpotify: z.boolean(),
|
||||
@@ -488,6 +489,7 @@ export const GeneralSettingsSchema = z.object({
|
||||
playerItems: z.array(SortableItemSchema(PlayerItemSchema)),
|
||||
playlistTarget: PlaylistTargetSchema,
|
||||
primaryShade: z.number().min(0).max(9),
|
||||
qobuz: z.boolean(),
|
||||
resume: z.boolean(),
|
||||
showLyricsInSidebar: z.boolean(),
|
||||
showRatings: z.boolean(),
|
||||
@@ -1132,6 +1134,7 @@ const initialState: SettingsState = {
|
||||
language: 'en',
|
||||
lastFM: true,
|
||||
lastfmApiKey: '',
|
||||
listenBrainz: true,
|
||||
musicBrainz: true,
|
||||
nativeAspectRatio: false,
|
||||
nativeSpotify: false,
|
||||
@@ -1150,6 +1153,7 @@ const initialState: SettingsState = {
|
||||
playerItems,
|
||||
playlistTarget: PlaylistTarget.TRACK,
|
||||
primaryShade: 6,
|
||||
qobuz: true,
|
||||
resume: true,
|
||||
showLyricsInSidebar: true,
|
||||
showRatings: true,
|
||||
@@ -2565,8 +2569,10 @@ export const useExternalLinks = () =>
|
||||
(state) => ({
|
||||
externalLinks: state.general.externalLinks,
|
||||
lastFM: state.general.lastFM,
|
||||
listenBrainz: state.general.listenBrainz,
|
||||
musicBrainz: state.general.musicBrainz,
|
||||
nativeSpotify: state.general.nativeSpotify,
|
||||
qobuz: state.general.qobuz,
|
||||
spotify: state.general.spotify,
|
||||
}),
|
||||
shallow,
|
||||
|
||||
Reference in New Issue
Block a user