mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-06 20:10:12 +02:00
add automatic country prioritization based on existing releases
This commit is contained in:
@@ -897,12 +897,14 @@
|
||||
"musicbrainz": "show MusicBrainz links",
|
||||
"musicBrainzQueries": "enable MusicBrainz integration",
|
||||
"musicBrainzQueries_description": "the integration will query MusicBrainz for missing artist releases and other miscellaneous data",
|
||||
"musicbrainzExcludeReleaseTypes": "exclude MusicBrainz release types",
|
||||
"musicbrainzExcludeReleaseTypes": "MusicBrainz release type exclusion",
|
||||
"musicbrainzExcludeReleaseTypes_description": "release types to exclude when loading MusicBrainz artist releases",
|
||||
"musicbrainzPrioritizeCountries": "prioritize MusicBrainz countries",
|
||||
"musicbrainzPrioritizeCountries": "MusicBrainz country priority",
|
||||
"musicbrainzPrioritizeCountries_description": "countries to prioritize when ordering MusicBrainz releases (first in list has highest priority)",
|
||||
"youtube": "enable youtube integration",
|
||||
"youtube_description": "external songs will attempt to use YouTube to resolve stream URLs for playback (desktop only)",
|
||||
"musicbrainzAutoCountryPriority": "automatic country priority",
|
||||
"musicbrainzAutoCountryPriority_description": "derive country priority from the artist's MusicBrainz releases (countries with more releases are ranked higher)",
|
||||
"youtube": "enable YouTube playback",
|
||||
"youtube_description": "external songs will attempt to use YouTube to resolve stream URLs (desktop only)",
|
||||
"neteaseTranslation_description": "When enabled, fetches and displays translated lyrics from NetEase if available",
|
||||
"neteaseTranslation": "Enable NetEase translations",
|
||||
"notify": "enable song notifications",
|
||||
|
||||
@@ -275,6 +275,7 @@ export const queryKeys: Record<
|
||||
limit: number | undefined,
|
||||
mbzArtistId: string,
|
||||
config?: {
|
||||
autoCountryPriority: boolean;
|
||||
excludeReleaseTypes: string[];
|
||||
prioritizeCountries: string[];
|
||||
},
|
||||
@@ -286,6 +287,7 @@ export const queryKeys: Record<
|
||||
limit,
|
||||
config
|
||||
? [
|
||||
String(config.autoCountryPriority),
|
||||
[...config.excludeReleaseTypes].sort().join(','),
|
||||
[...config.prioritizeCountries].sort().join(','),
|
||||
]
|
||||
|
||||
@@ -1381,6 +1381,9 @@ const ArtistAlbums = ({ albumsQuery }: ArtistAlbumsProps) => {
|
||||
const musicBrainzExcludeReleaseTypes = useSettingsStore(
|
||||
(state) => state.integrations.musicBrainzExcludeReleaseTypes,
|
||||
);
|
||||
const musicbrainzAutoCountryPriority = useSettingsStore(
|
||||
(state) => state.integrations.musicbrainzAutoCountryPriority,
|
||||
);
|
||||
const musicBrainzPrioritizeCountries = useSettingsStore(
|
||||
(state) => state.integrations.musicBrainzPrioritizeCountries,
|
||||
);
|
||||
@@ -1410,6 +1413,7 @@ const ArtistAlbums = ({ albumsQuery }: ArtistAlbumsProps) => {
|
||||
const musicBrainzEnabled = useSettingsStore((state) => state.integrations.musicBrainz);
|
||||
const musicbrainzArtistQuery = useQuery({
|
||||
...musicbrainzQueries.artist({
|
||||
autoCountryPriority: musicbrainzAutoCountryPriority,
|
||||
excludeReleaseTypes: musicBrainzExcludeReleaseTypes,
|
||||
mbzArtistId: detailQuery.data?.mbz as string,
|
||||
prioritizeCountries: musicBrainzPrioritizeCountries,
|
||||
@@ -1418,6 +1422,7 @@ const ArtistAlbums = ({ albumsQuery }: ArtistAlbumsProps) => {
|
||||
meta: {
|
||||
albumArtist: detailQuery.data,
|
||||
albums: albumsQuery.data?.items || [],
|
||||
autoCountryPriority: musicbrainzAutoCountryPriority,
|
||||
excludeReleaseTypes: musicBrainzExcludeReleaseTypes,
|
||||
prioritizeCountries: musicBrainzPrioritizeCountries,
|
||||
},
|
||||
|
||||
@@ -40,6 +40,7 @@ export type IRelationWithWork = IRelation & { work?: IWork };
|
||||
export type MusicBrainzArtistSelectMeta = {
|
||||
albumArtist: AlbumArtist;
|
||||
albums?: Album[];
|
||||
autoCountryPriority?: boolean;
|
||||
excludeReleaseTypes?: string[];
|
||||
prioritizeCountries?: string[];
|
||||
};
|
||||
@@ -123,7 +124,22 @@ const artistSelect = memoize(
|
||||
|
||||
const excludeReleaseTypes = (meta.excludeReleaseTypes ?? []).map((t) => t.toLowerCase());
|
||||
const excludeSet = new Set(excludeReleaseTypes);
|
||||
const prioritizeCountries = (meta.prioritizeCountries ?? []).map((c) => c.toUpperCase());
|
||||
|
||||
let prioritizeCountries: string[];
|
||||
if (meta.autoCountryPriority) {
|
||||
const countryCounts = new Map<string, number>();
|
||||
for (const release of data.releases.releases) {
|
||||
const country = release.country?.toUpperCase();
|
||||
if (country) {
|
||||
countryCounts.set(country, (countryCounts.get(country) ?? 0) + 1);
|
||||
}
|
||||
}
|
||||
prioritizeCountries = [...countryCounts.entries()]
|
||||
.sort(([, a], [, b]) => b - a)
|
||||
.map(([code]) => code);
|
||||
} else {
|
||||
prioritizeCountries = (meta.prioritizeCountries ?? []).map((c) => c.toUpperCase());
|
||||
}
|
||||
|
||||
const releaseEntries = Array.from(unownedReleases.entries())
|
||||
.filter(([, release]) => {
|
||||
@@ -290,11 +306,13 @@ const EMPTY_BROWSE_RELEASES: IBrowseReleasesResult = {
|
||||
|
||||
export const musicbrainzQueries = {
|
||||
artist: (args: {
|
||||
autoCountryPriority?: boolean;
|
||||
excludeReleaseTypes?: string[];
|
||||
mbzArtistId: string;
|
||||
prioritizeCountries?: string[];
|
||||
}) => {
|
||||
const config = {
|
||||
autoCountryPriority: args.autoCountryPriority ?? false,
|
||||
excludeReleaseTypes: args.excludeReleaseTypes ?? [],
|
||||
prioritizeCountries: args.prioritizeCountries ?? [],
|
||||
};
|
||||
|
||||
@@ -378,6 +378,27 @@ export const IntegrationsTab = memo(() => {
|
||||
isHidden: !musicBrainz || !settings.musicBrainz,
|
||||
title: t('setting.musicbrainzPrioritizeCountries', { postProcess: 'sentenceCase' }),
|
||||
},
|
||||
{
|
||||
control: (
|
||||
<Switch
|
||||
aria-label={t('setting.musicbrainzAutoCountryPriority', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
defaultChecked={settings.musicbrainzAutoCountryPriority}
|
||||
onChange={(e) =>
|
||||
updateIntegrations({
|
||||
musicbrainzAutoCountryPriority: e.currentTarget.checked,
|
||||
})
|
||||
}
|
||||
/>
|
||||
),
|
||||
description: t('setting.musicbrainzAutoCountryPriority', {
|
||||
context: 'description',
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
isHidden: !musicBrainz || !settings.musicBrainz,
|
||||
title: t('setting.musicbrainzAutoCountryPriority', { postProcess: 'sentenceCase' }),
|
||||
},
|
||||
{
|
||||
control: (
|
||||
<Switch
|
||||
@@ -397,10 +418,7 @@ export const IntegrationsTab = memo(() => {
|
||||
|
||||
return (
|
||||
<Stack gap="md">
|
||||
<SettingsSection
|
||||
options={options}
|
||||
title={t('page.setting.integrationsTab', { postProcess: 'sentenceCase' })}
|
||||
/>
|
||||
<SettingsSection options={options} title={'MusicBrainz'} />
|
||||
</Stack>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -614,6 +614,7 @@ const QueryBuilderSettingsSchema = z.object({
|
||||
});
|
||||
|
||||
const IntegrationsSettingsSchema = z.object({
|
||||
musicbrainzAutoCountryPriority: z.boolean(),
|
||||
musicBrainz: z.boolean(),
|
||||
musicBrainzExcludeReleaseTypes: z.array(z.string()),
|
||||
musicBrainzPrioritizeCountries: z.array(z.string()),
|
||||
@@ -1105,6 +1106,7 @@ const initialState: SettingsState = {
|
||||
globalMediaHotkeys: true,
|
||||
},
|
||||
integrations: {
|
||||
musicbrainzAutoCountryPriority: false,
|
||||
musicBrainz: true,
|
||||
musicBrainzExcludeReleaseTypes: [],
|
||||
musicBrainzPrioritizeCountries: [],
|
||||
@@ -2108,6 +2110,7 @@ export const useSettingsStore = createWithEqualityFn<SettingsSlice>()(
|
||||
// Move MusicBrainz release/country options to Integrations; keep musicBrainz in general
|
||||
const general = state.general as Record<string, unknown>;
|
||||
state.integrations = {
|
||||
musicbrainzAutoCountryPriority: initialState.integrations.musicbrainzAutoCountryPriority,
|
||||
musicBrainz: initialState.integrations.musicBrainz,
|
||||
musicBrainzExcludeReleaseTypes:
|
||||
(general?.musicBrainzExcludeReleaseTypes as string[]) ??
|
||||
@@ -2130,10 +2133,19 @@ export const useSettingsStore = createWithEqualityFn<SettingsSlice>()(
|
||||
};
|
||||
}
|
||||
|
||||
if (version <= 26) {
|
||||
state.integrations = {
|
||||
...state.integrations,
|
||||
musicbrainzAutoCountryPriority:
|
||||
(state.integrations as { musicbrainzAutoCountryPriority?: boolean })
|
||||
?.musicbrainzAutoCountryPriority ?? false,
|
||||
};
|
||||
}
|
||||
|
||||
return persistedState;
|
||||
},
|
||||
name: 'store_settings',
|
||||
version: 26,
|
||||
version: 27,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user