more lint fixes

This commit is contained in:
ChrisScott9456
2026-07-12 14:04:53 -04:00
parent dd0b645ee4
commit 030ecca898
10 changed files with 88 additions and 82 deletions
+12 -12
View File
@@ -786,6 +786,18 @@ export const controller: GeneralController = {
server.type,
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
},
refreshItems(args) {
const server = getServerById(args.apiClientProps.serverId);
if (!server) {
throw new Error(`${i18n.t('error.apiRouteError')}: refreshItems`);
}
return apiController(
'refreshItems',
server.type,
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
},
removeFromPlaylist(args) {
const server = getServerById(args.apiClientProps.serverId);
@@ -888,18 +900,6 @@ export const controller: GeneralController = {
server.type,
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
},
refreshItems(args) {
const server = getServerById(args.apiClientProps.serverId);
if (!server) {
throw new Error(`${i18n.t('error.apiRouteError')}: refreshItems`);
}
return apiController(
'refreshItems',
server.type,
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
},
updateInternetRadioStation(args) {
const server = getServerById(args.apiClientProps.serverId);
+12 -12
View File
@@ -301,6 +301,18 @@ export const contract = c.router({
400: jfType._response.error,
},
},
refreshItem: {
body: z.null(),
method: 'POST',
path: 'Items/:id/Refresh',
query: z.object({
MetadataRefreshMode: z.string().optional(),
}),
responses: {
204: z.null(),
400: jfType._response.error,
},
},
removeFavorite: {
body: jfType._parameters.favorite,
method: 'DELETE',
@@ -365,18 +377,6 @@ export const contract = c.router({
400: jfType._response.error,
},
},
refreshItem: {
body: z.null(),
method: 'POST',
path: 'Items/:id/Refresh',
query: z.object({
MetadataRefreshMode: z.string().optional(),
}),
responses: {
204: z.null(),
400: jfType._response.error,
},
},
updatePlaylist: {
body: jfType._parameters.updatePlaylist,
method: 'POST',
@@ -1556,6 +1556,21 @@ export const JellyfinController: InternalControllerEndpoint = {
throw new Error('Failed to move item in playlist');
}
},
refreshItems: async (args) => {
const { apiClientProps, query } = args;
await Promise.all(
query.ids.map((id) =>
jfApiClient(apiClientProps).refreshItem({
body: null,
params: { id },
query: { MetadataRefreshMode: 'FullRefresh' },
}),
),
);
return null;
},
removeFromPlaylist: async (args) => {
const { apiClientProps, query } = args;
@@ -1874,21 +1889,6 @@ export const JellyfinController: InternalControllerEndpoint = {
return null;
},
refreshItems: async (args) => {
const { apiClientProps, query } = args;
await Promise.all(
query.ids.map((id) =>
jfApiClient(apiClientProps).refreshItem({
body: null,
params: { id },
query: { MetadataRefreshMode: 'FullRefresh' },
}),
),
);
return null;
},
updateInternetRadioStation: async (args) => {
const { apiClientProps, body, query } = args;
@@ -1027,6 +1027,7 @@ export const NavidromeController: InternalControllerEndpoint = {
throw new Error('Failed to move item in playlist');
}
},
refreshItems: SubsonicController.refreshItems,
removeFromPlaylist: async (args) => {
const { apiClientProps, query } = args;
@@ -1185,7 +1186,6 @@ export const NavidromeController: InternalControllerEndpoint = {
id: res.body.data.id,
};
},
refreshItems: SubsonicController.refreshItems,
updateInternetRadioStation: async (args) => {
const { apiClientProps, body, query } = args;
@@ -2082,6 +2082,17 @@ export const SubsonicController: InternalControllerEndpoint = {
return res.body;
},
refreshItems: async (args) => {
const { apiClientProps } = args;
const res = await ssApiClient(apiClientProps).startScan({ query: {} });
if (res.status !== 200) {
throw new Error('Failed to start scan');
}
return null;
},
removeFromPlaylist: async ({ apiClientProps, query }) => {
const res = await ssApiClient(apiClientProps).updatePlaylist({
query: {
@@ -2356,17 +2367,6 @@ export const SubsonicController: InternalControllerEndpoint = {
return null;
},
refreshItems: async (args) => {
const { apiClientProps } = args;
const res = await ssApiClient(apiClientProps).startScan({ query: {} });
if (res.status !== 200) {
throw new Error('Failed to start scan');
}
return null;
},
updateInternetRadioStation: async (args) => {
const { apiClientProps, body, query } = args;
@@ -15,7 +15,7 @@ type SongEditInnerProps = {
export const SongEditContextModal = ({ innerProps }: ContextModalProps<SongEditInnerProps>) => {
const server = useCurrentServer();
const [resolvedSongs, setResolvedSongs] = useState<Song[] | null>(null);
const [resolvedSongs, setResolvedSongs] = useState<null | Song[]>(null);
useEffect(() => {
if (innerProps.albumIds) {
@@ -1,8 +1,8 @@
import { Autocomplete } from '@mantine/core';
import { closeAllModals } from '@mantine/modals';
import { useRef, useState } from 'react';
import { RiAddLine } from 'react-icons/ri';
import { useTranslation } from 'react-i18next';
import { RiAddLine } from 'react-icons/ri';
import { useMetadataEditor } from '../hooks/use-metadata-editor';
import { KNOWN_TAG_MAP, resolveTagKey } from '../utils/known-tags';
@@ -40,14 +40,17 @@ export const SongEditModal = ({ songs }: { songs: Song[] }) => {
trimmedInput && !KNOWN_TAG_MAP.has(trimmedInput)
? trimmedInput.includes('=')
? "Tag key cannot contain '='"
: /[^\x00-\x7F]/.test(trimmedInput)
: // eslint-disable-next-line no-control-regex
/[^\x00-\x7F]/.test(trimmedInput)
? 'Tag key must use ASCII characters only'
: null
: null;
const resolvedInputKey = trimmedInput ? resolveTagKey(trimmedInput) : '';
const duplicateError =
trimmedInput && !customKeyError && editor.sortedFieldEntries.some(([k]) => k === resolvedInputKey)
trimmedInput &&
!customKeyError &&
editor.sortedFieldEntries.some(([k]) => k === resolvedInputKey)
? 'Field already exists'
: null;
const fieldError = customKeyError ?? (duplicateAttempted ? duplicateError : null);
@@ -55,7 +58,12 @@ export const SongEditModal = ({ songs }: { songs: Song[] }) => {
const handleAddField = (key: string): boolean => {
const trimmed = key.trim();
if (!trimmed) return false;
if (!KNOWN_TAG_MAP.has(trimmed) && (trimmed.includes('=') || /[^\x00-\x7F]/.test(trimmed))) return false;
if (
!KNOWN_TAG_MAP.has(trimmed) &&
(trimmed.includes('=') || // eslint-disable-next-line no-control-regex
/[^\x00-\x7F]/.test(trimmed))
)
return false;
const normalizedKey = resolveTagKey(trimmed);
if (editor.sortedFieldEntries.some(([k]) => k === normalizedKey)) {
setDuplicateAttempted(true);
@@ -25,14 +25,20 @@ export type TagFieldType = 'boolean' | 'number' | 'string' | 'textarea';
* label/type overridden; keys absent from PROPERTIES are appended as extra entries.
*/
const TAG_CONFIG: Record<string, { label?: string; type?: TagFieldType }> = {
acoustidFingerprint: { type: 'textarea' },
acoustidId: { label: 'AcoustID' },
albumArtist: { label: 'Album Artist' },
albumArtistSort: { label: 'Album Artist Sort' },
albumSort: { label: 'Album Sort' },
// extras not in PROPERTIES (common MusicBrainz Picard tags)
ARTISTS: { label: 'Artists', type: 'string' },
artistSort: { label: 'Artist Sort' },
bpm: { type: 'number' },
catalogNumber: { label: 'Catalog Number' },
comment: { type: 'textarea' },
composerSort: { label: 'Composer Sort' },
discNumber: { label: 'Disc Number' },
lyrics: { type: 'textarea' },
musicbrainzArtistId: { label: 'MusicBrainz Artist ID' },
musicbrainzReleaseArtistId: { label: 'MusicBrainz Album Artist ID' },
musicbrainzReleaseGroupId: { label: 'MusicBrainz Release Group ID' },
@@ -43,21 +49,15 @@ const TAG_CONFIG: Record<string, { label?: string; type?: TagFieldType }> = {
originalAlbum: { label: 'Original Album' },
originalArtist: { label: 'Original Artist' },
originalDate: { label: 'Original Date' },
ORIGINALYEAR: { label: 'Original Year', type: 'number' },
RELEASECOUNTRY: { label: 'Release Country', type: 'string' },
RELEASESTATUS: { label: 'Release Status', type: 'string' },
RELEASETYPE: { label: 'Release Type', type: 'string' },
remixedBy: { label: 'Remixer' },
titleSort: { label: 'Title Sort' },
totalDiscs: { label: 'Total Discs' },
totalTracks: { label: 'Total Tracks' },
trackNumber: { label: 'Track Number' },
acoustidFingerprint: { type: 'textarea' },
bpm: { type: 'number' },
comment: { type: 'textarea' },
lyrics: { type: 'textarea' },
// extras not in PROPERTIES (common MusicBrainz Picard tags)
ARTISTS: { label: 'Artists', type: 'string' },
ORIGINALYEAR: { label: 'Original Year', type: 'number' },
RELEASECOUNTRY: { label: 'Release Country', type: 'string' },
RELEASESTATUS: { label: 'Release Status', type: 'string' },
RELEASETYPE: { label: 'Release Type', type: 'string' },
};
const humanizeKey = (key: string): string =>