Add global context modal for song edit and move album fetch to it

This commit is contained in:
ChrisScott9456
2026-06-28 20:46:15 -04:00
parent 56f05ddafc
commit 8917a5d076
3 changed files with 72 additions and 34 deletions
@@ -1,11 +1,8 @@
import { openModal } from '@mantine/modals';
import { openContextModal } from '@mantine/modals';
import isElectron from 'is-electron';
import { useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { controller } from '/@/renderer/api/controller';
import { SongEditModal } from '/@/renderer/features/tag-editor/components/song-edit-modal';
import { useCurrentServer } from '/@/renderer/store';
import { ContextMenu } from '/@/shared/components/context-menu/context-menu';
import { Song } from '/@/shared/types/domain-types';
@@ -16,44 +13,20 @@ interface EditMetadataActionProps {
const utils = isElectron() ? window.api.utils : null;
const getAlbumSongs = async (albumIds: string[], serverId: string): Promise<Song[]> => {
const albumDetails = await Promise.all(
albumIds.map((id) =>
controller.getAlbumDetail({
apiClientProps: { serverId },
query: { id },
}),
),
);
return albumDetails.flatMap((album) => album?.songs ?? []).filter((s) => s.path);
};
export const EditMetadataAction = ({ albumIds, songs: songItems }: EditMetadataActionProps) => {
const { t } = useTranslation();
const server = useCurrentServer();
const songs = useMemo(() => songItems?.filter((s) => s.path) ?? [], [songItems]);
const count = albumIds?.length ?? songs.length;
const onSelect = useCallback(async () => {
let resolvedSongs: Song[];
if (albumIds) {
resolvedSongs = server?.id ? await getAlbumSongs(albumIds, server.id) : [];
} else {
resolvedSongs = songs;
}
const trackCount = resolvedSongs.length;
openModal({
children: <SongEditModal songs={resolvedSongs} />,
const onSelect = useCallback(() => {
openContextModal({
innerProps: { albumIds, songs },
modal: 'editMetadata',
size: 'xl',
styles: { body: { paddingBottom: 'var(--theme-spacing-xl)' } },
title:
trackCount > 1
? `${t('page.contextMenu.editMetadata')} (${trackCount} ${t('common.tracks', 'tracks')})`
: t('page.contextMenu.editMetadata'),
title: t('page.contextMenu.editMetadata'),
});
}, [albumIds, server, songs, t]);
}, [albumIds, songs, t]);
if (!utils) return null;
@@ -0,0 +1,52 @@
import { ContextModalProps } from '@mantine/modals';
import { useEffect, useState } from 'react';
import { controller } from '/@/renderer/api/controller';
import { SongEditModal } from '/@/renderer/features/tag-editor/components/song-edit-modal';
import { useCurrentServer } from '/@/renderer/store';
import { Spinner } from '/@/shared/components/spinner/spinner';
import { Stack } from '/@/shared/components/stack/stack';
import { Song } from '/@/shared/types/domain-types';
type SongEditInnerProps = {
albumIds?: string[];
songs?: Song[];
};
export const SongEditContextModal = ({ innerProps }: ContextModalProps<SongEditInnerProps>) => {
const server = useCurrentServer();
const [resolvedSongs, setResolvedSongs] = useState<Song[] | null>(null);
useEffect(() => {
if (innerProps.albumIds) {
if (!server?.id) {
setResolvedSongs([]);
return;
}
Promise.all(
innerProps.albumIds.map((id) =>
controller.getAlbumDetail({
apiClientProps: { serverId: server.id },
query: { id },
}),
),
).then((albums) => {
setResolvedSongs(
albums.flatMap((album) => album?.songs ?? []).filter((s) => s.path),
);
});
} else {
setResolvedSongs((innerProps.songs ?? []).filter((s) => s.path));
}
}, [innerProps.albumIds, innerProps.songs, server?.id]);
if (resolvedSongs === null) {
return (
<Stack align="center" p="xl">
<Spinner />
</Stack>
);
}
return <SongEditModal songs={resolvedSongs} />;
};
+13
View File
@@ -175,9 +175,22 @@ const VisualizerSettingsContextModal = (props: any) => (
</Suspense>
);
const LazySongEditContextModal = lazy(() =>
import('/@/renderer/features/tag-editor/components/song-edit-context-modal').then((module) => ({
default: module.SongEditContextModal,
})),
);
const SongEditContextModal = (props: any) => (
<Suspense fallback={<Spinner container />}>
<LazySongEditContextModal {...props} />
</Suspense>
);
const appRouterModals = {
addToPlaylist: AddToPlaylistContextModal,
base: BaseContextModal,
editMetadata: SongEditContextModal,
lyricsSettings: LyricsSettingsContextModal,
saveAndReplace: SaveAndReplaceContextModal,
settings: SettingsContextModal,