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.6 kB · 90 lines
TSX
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990import { Alert, Box, Code, Collapsible, HStack, Span, Stack, Text, useCollapsible, type UseCollapsibleReturn } from '@chakra-ui/react';import { Fragment, useEffect, useState, type ComponentProps } from 'react';import { isErrorIsh, type ErrorIsh } from '../../core/ErrorUtils';import { ChakraClip } from './ChakraClipboard';import { ChakraCodeBlock } from './CodeBlock';import { EllipsisButton, FatArrowRight } from './icons/ChakraIcons';import { walkError, type ErrorData } from '../utils/ComponentUtils';
export interface ErrorAlertProps { error: ErrorIsh status?: "error" | "info" | "warning" | "success" | "neutral"}
const ErrorBlock = (props: {data: ErrorData, cause?: boolean, messageProps?: ComponentProps<typeof Text>, collapsible: UseCollapsibleReturn}) => { const { data, cause, collapsible, messageProps = {} } = props;
const [open, setOpen] = useState(collapsible.open); useEffect(() => { setOpen(collapsible.open); }, [setOpen, collapsible]);
const textProps: ComponentProps<typeof Text> = {...(cause ? {color: "fg.muted"} : {}), ...messageProps}; const containerProps: ComponentProps<typeof HStack> = {}; if(cause) { containerProps.paddingLeft = "2"; } const errorIdentifier = `${data.name ?? ''}${data.code !== undefined ? ` (${data.code}) ` : ''}`; const errorElm = errorIdentifier === '' ? null : <Code variant="surface" mx="1">{errorIdentifier}</Code> const messageElm: React.JSX.Element = ( <HStack {...containerProps}> {cause ? <FatArrowRight/> : null} <Text {...textProps}>{cause ? <Span fontWeight="semibold">Caused By: </Span> : ''}{errorElm}{data.message}</Text> </HStack>
);
if(data.stack === undefined) { return messageElm; }
return ( <> <Box hideFrom="md">{messageElm}</Box> <Collapsible.Root hideBelow="md" open={open} onOpenChange={(val) => setOpen(val.open)}> <HStack>{messageElm}<Collapsible.Trigger><EllipsisButton size="2xs"/></Collapsible.Trigger></HStack> <Collapsible.Content paddingY="2"> <ChakraCodeBlock language="plaintext" code={data.stack} title="Stack" maxLines={6} collapsedMaxHeight="10em" hideBelow="sm"/> </Collapsible.Content> </Collapsible.Root> </> )}
export const ErrorAlert = (props: ErrorAlertProps) => {
if(!isErrorIsh(props.error)) { return null; } let causes: ErrorData[] = []; if(isErrorIsh(props.error.cause)) { causes = walkError(props.error.cause); }
const collapsible = useCollapsible()
return ( <Alert.Root status={props.status ?? 'error'}> <Alert.Indicator /> <Alert.Content> <Alert.Title>{props.error.name ?? 'Error'}<EllipsisButton hideBelow="md" marginLeft="2" size="2xs" onClick={() => collapsible.setOpen(!collapsible.open)}/></Alert.Title> <Alert.Description> <Stack gap="0.5"> <ErrorBlock data={props.error} messageProps={{fontWeight: 'semibold'}} collapsible={collapsible}/> {causes.map((x, index) => ( <Fragment key={index}> <ErrorBlock key={index} data={x} cause collapsible={collapsible}/> </Fragment> ))} </Stack> </Alert.Description> </Alert.Content> <ChakraClip value={props.error}/> </Alert.Root> )}