[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
0

Configure Feed

Select the types of activity you want to include in your feed.

feat(ui): Hide text-heavy elements for small mobile

FoxxMD (Mar 19, 2026, 9:11 PM UTC) 60cf5d10 3977057d

+44 -35
+37 -28
src/client/components/ActivityTimeline.tsx
··· 1 1 import { ComponentProps, useState } from "react" 2 - import { Accordion, Timeline, Icon, Span, Stack, Heading, Card, Box } from '@chakra-ui/react'; 2 + import { Accordion, Timeline, Icon, Span, Stack, Heading, Card, Box, Tabs } from '@chakra-ui/react'; 3 3 import { ErrorLike, JsonPlayObject, PlayActivity } from "../../core/Atomic"; 4 4 import { PlayData } from "./PlayData"; 5 5 import { ErrorAlert } from "./ErrorAlert"; ··· 63 63 </Timeline.Connector> 64 64 <Timeline.Content> 65 65 <Timeline.Title> 66 - Discovered <Span color="fg.muted">new activity from</Span> 66 + Discovered <Span color="fg.muted">new (Play) activity from</Span> 67 67 <Span fontWeight="medium">{capitalize(source)}</Span> 68 68 <Span color="fg.muted">at {shortTodayAwareFormat(dayjs(playDate))}</Span> 69 69 </Timeline.Title> 70 - <ChakraCodeBlockShort code={input} /> 71 - </Timeline.Content> 72 - </Timeline.Item> 73 - 74 - <Timeline.Item> 75 - <Timeline.Connector> 76 - <Timeline.Separator /> 77 - <Timeline.Indicator> 78 - <Icon fontSize="xs"> 79 - <IoMusicalNoteOutline /> 80 - </Icon> 81 - </Timeline.Indicator> 82 - </Timeline.Connector> 83 - <Timeline.Content> 84 - <Timeline.Title> 85 - <Span color="fg.muted">Created new</Span> Play 86 - </Timeline.Title> 87 - <PlayData play={original} /> 70 + <Card.Root bgColor="bg.muted" size="sm" hideBelow="sm"> 71 + <Card.Body textStyle="sm"> 72 + <Tabs.Root size="sm" variant="outline" defaultValue="play"> 73 + <Tabs.List> 74 + <Tabs.Trigger value="play">Play</Tabs.Trigger> 75 + <Tabs.Trigger value="source">Source Data</Tabs.Trigger> 76 + </Tabs.List> 77 + <Tabs.Content value="play"> 78 + <PlayData play={original} /> 79 + </Tabs.Content> 80 + <Tabs.Content value="source"> 81 + <ChakraCodeBlockShort code={input} /> 82 + </Tabs.Content> 83 + </Tabs.Root> 84 + </Card.Body> 85 + </Card.Root> 88 86 </Timeline.Content> 89 87 </Timeline.Item> 90 88 {steps.length > 0 ? ( ··· 99 97 </Timeline.Connector> 100 98 <Timeline.Content gap="4"> 101 99 <Timeline.Title> 102 - Transforms 100 + Transformed Play <Span color="fg.muted">using configured Rules</Span> 103 101 </Timeline.Title> 104 - <TransformSteps steps={steps} original={original} collapsibleOpen={collapsibleOpen}/> 102 + <Card.Root bgColor="bg.muted" size="sm"> 103 + <Card.Body textStyle="sm"> 104 + <TransformSteps steps={steps} original={original} collapsibleOpen={collapsibleOpen} /> 105 + </Card.Body> 106 + </Card.Root> 105 107 </Timeline.Content> 106 108 </Timeline.Item> 107 109 ) : null} ··· 117 119 </Timeline.Connector> 118 120 <Timeline.Content gap="4"> 119 121 <Timeline.Title> 120 - Duplicate Match Check 122 + <Span color="fg.muted">Found </Span>{match.match ? <Span color="orange.solid"> a duplicate Scrobble</Span> : 'no duplicate Scrobbles'} 121 123 </Timeline.Title> 122 - {match.reason} 123 - <MSCollapsible indicator="Show Details" defaultOpen={collapsibleOpen}> 124 - <ScrobbleMatchResult match={match}/> 125 - </MSCollapsible> 124 + <Card.Root bgColor="bg.muted" size="sm" hideBelow="sm"> 125 + <Card.Body textStyle="sm"> 126 + <MSCollapsible indicator="Show Details" defaultOpen={collapsibleOpen}> 127 + <ScrobbleMatchResult match={match} /> 128 + </MSCollapsible> 129 + </Card.Body> 130 + </Card.Root> 126 131 </Timeline.Content> 127 132 </Timeline.Item> 128 133 ) : null} ··· 140 145 <Timeline.Title> 141 146 <Span color="fg.muted">Attmpted to</Span> Scrobble 142 147 </Timeline.Title> 143 - <ScrobbleActionResult result={scrobble} scrobbler="Koito" collapsibleOpen={collapsibleOpen}/> 148 + <Card.Root bgColor="bg.muted" size="sm"> 149 + <Card.Body textStyle="sm"> 150 + <ScrobbleActionResult result={scrobble} scrobbler="Koito" collapsibleOpen={collapsibleOpen} /> 151 + </Card.Body> 152 + </Card.Root> 144 153 </Timeline.Content> 145 154 </Timeline.Item> 146 155 ) : null}
+3 -3
src/client/components/PlayData.tsx
··· 61 61 62 62 if (!comparable) { 63 63 return (<Box position="relative"> 64 - <Float placement="top-end" offsetX="3" hideBelow="sm" zIndex={100}>{code}</Float> 64 + <Float placement="top-end" offsetX="4" offsetY="2" hideBelow="sm" zIndex={100}>{code}</Float> 65 65 {codeMode ? <ChakraCodeBlock code={play} /> : <PlayDataDataList play={play} dates={dates} />} 66 66 </Box>); 67 67 } 68 68 69 69 return ( 70 70 <Box position="relative"> 71 - <Float placement="top-end" offsetX="3" offsetY="2" hideBelow="sm" zIndex={100}>{code}</Float> 72 - <Tabs.Root defaultValue={compareDefault}> 71 + <Float placement="top-end" offsetX="4" offsetY="2" hideBelow="sm" zIndex={100}>{code}</Float> 72 + <Tabs.Root size="sm" variant="outline" defaultValue={compareDefault}> 73 73 <Tabs.List> 74 74 <Tabs.Trigger value="Initial">Initial</Tabs.Trigger> 75 75 <Tabs.Trigger value="Final">Final</Tabs.Trigger>
+2 -2
src/client/components/ScrobbleActionResult.tsx
··· 47 47 <Timeline.Title> 48 48 <Span color="fg.muted">Sent</Span> Scrobble Payload{scrobbler !== undefined ? <Fragment><Span color="fg.muted">to</Span> {capitalize(scrobbler)}</Fragment> : null} 49 49 </Timeline.Title> 50 - <MSCollapsible indicator="Show Payload" defaultOpen={collapsibleOpen}> 50 + <MSCollapsible indicator="Show Payload" defaultOpen={collapsibleOpen} hideBelow="sm"> 51 51 <ChakraCodeBlockShort code={payload} language="json" maxLines={20} /> 52 52 </MSCollapsible> 53 53 </Timeline.Content> ··· 66 66 <Timeline.Title> 67 67 <Span color="fg.muted">Received</Span> Response{scrobbler !== undefined ? <Fragment><Span color="fg.muted">from</Span> {capitalize(scrobbler)}</Fragment> : null}{warnings.length > 0 ? <Span color="orange.solid"> with warnings</Span> : null} 68 68 </Timeline.Title> 69 - <MSCollapsible indicator="Show Response" defaultOpen={collapsibleOpen}> 69 + <MSCollapsible indicator="Show Response" defaultOpen={collapsibleOpen} hideBelow="sm"> 70 70 <ChakraCodeBlockShort code={response} language="json" maxLines={20} /> 71 71 {warnings.length > 0 ? ( 72 72 <Alert.Root status="warning">
+2 -2
src/client/components/TransformSteps.tsx
··· 50 50 <Timeline.Title> 51 51 {x.name} <Span color="fg.muted">with</Span> {x.source} 52 52 </Timeline.Title> 53 - <MSCollapsible indicator="Show Details" defaultOpen={collapsibleOpen}> 53 + <MSCollapsible indicator="Show Details" defaultOpen={collapsibleOpen} hideBelow="sm"> 54 54 <Heading size="sm">Diff</Heading> 55 55 {err !== undefined ? <ErrorAlert error={err} /> : null} 56 56 ··· 70 70 </Timeline.Item> 71 71 })} 72 72 {currentPlay !== false ? ( 73 - <Timeline.Item> 73 + <Timeline.Item hideBelow="sm"> 74 74 <Timeline.Connector> 75 75 <Timeline.Separator /> 76 76 <Timeline.Indicator>