Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/FoxxMD/multi-scrobbler. Scrobble plays from multiple sources to multiple clients docs.multi-scrobbler.app
deezer docker jellyfin koito lastfm listenbrainz maloja mopidy mpris music music-assistant plex scrobble self-hosted spotify subsonic tautulli youtube-music
Something went wrong. Try again.
3.4 kB · 92 lines
TSX
at master
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192import { useListCollection, Stack, Text, HStack } from "@chakra-ui/react"import { useDebouncedState } from '@tanstack/react-pacer'import { useQuery } from '@tanstack/react-query';import { tanQueries } from "../../queries/index.js";import { type ArtistSearchResult } from "../../../core/Api.js";import { useCallback, useEffect, useState } from "react";import { LeftSideMetadataResultContent, MetadataPickMenu, MetadataSearchCombobox, type MetadataPartials } from "./MetadataResults.js";import { creditSchema, type Credit } from "../../../core/Atomic.js";import { MusicServiceIndicators } from "../musicServices/MusicServiceIndicators.js";
const artistPartials: MetadataPartials<ArtistSearchResult> = { name: { label: 'Name only', pick: ({ image, metadata, ...rest }) => rest },};
export const ArtistSearchResultItem = (props: { data: ArtistSearchResult, onPick?: (val: ArtistSearchResult) => void }) => {
const { name, metadata = [] } = props.data;
return ( <HStack gap="4" flexGrow="1"> <LeftSideMetadataResultContent {...props.data} /> <Stack gap="1" flexGrow="1"> <Text fontWeight="medium"> <HStack> {name} <MusicServiceIndicators services={metadata}/> <MetadataPickMenu data={props.data} partials={artistPartials} onPick={props.onPick} /> </HStack> </Text> </Stack> </HStack> )}
export interface ArtistSearchProps { initial?: Credit onChange: (val: Credit) => void}
export const ArtistSearch = (props: ArtistSearchProps) => {
const { initial, onChange = (val) => console.log(val, 'Selected value for prop') } = props;
const [selectedItem, setSelectedItem] = useState<Credit>(initial ?? {name: ''}); const [debouncedQuery, setDebouncedQuery] = useDebouncedState<string>(initial?.name ?? '', { wait: 500 });
const query = useQuery({ enabled: debouncedQuery !== '', ...tanQueries.metadata.artists(debouncedQuery) });
const { collection, set } = useListCollection<ArtistSearchResult>({ initialItems: query.data?.data ?? [], itemToString: (item) => item.name, itemToValue: (item) => item.id, });
useEffect(() => { if (query.isSuccess) { set(query.data.data); } }, [query, set])
const doChange = useCallback((val: Credit) => { // drops the search-only properties of a result const credit = creditSchema.parse(val); setSelectedItem(credit); onChange(credit); },[setSelectedItem, onChange]);
const services = selectedItem.metadata ?? []; let groupContent: React.JSX.Element | undefined = undefined; if(services.length > 0) { groupContent = <MusicServiceIndicators services={services} link={false}/> }
return ( <MetadataSearchCombobox placeholder="Type to search for artists" collection={collection} inputGroupContent={groupContent} initialInput={selectedItem?.name} isLoading={query.isLoading} isError={query.isError} onChange={doChange} onFreetext={(name) => doChange({ name })} onQueryChange={setDebouncedQuery} renderItem={(item, onPick) => <ArtistSearchResultItem data={item} onPick={onPick} />} /> );}