Pick the music services you use
CI / check (push) Canceled after 0s

Songs offered links to all five services. Settings now has "Your music
services": pick the ones you use and songs only show those, with the
main one as the big button. Until someone picks, they still see all of
them. Onboarding sets it to the app you said you listen with.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-14 20:45:29 -04:00
co-authored by Claude Opus 5.5
parent 08631589e3
commit d00eb6674e
16 changed files with 1607 additions and 13 deletions
+28 -6
View File
@@ -10,6 +10,7 @@ import {
type ConnectionDTO,
type MeDTO,
type NowPlayingProvider,
type StreamingService,
} from '@musicshare/shared';
import { Avatar } from '@/components/Avatar';
import { RelinkReminder } from '@/components/RelinkReminder';
@@ -34,7 +35,7 @@ export default function SettingsScreen() {
<ProfileSection />
<SharingControls />
<RelinkReminder />
<PreferredService />
<MyServices />
<ThisPhone />
<Connections />
<FeaturedPicker />
@@ -118,23 +119,44 @@ function AvatarPicker() {
);
}
function PreferredService() {
/** The services you use: songs offer only these, and open in the main one. */
function MyServices() {
const { me, setMe } = useSession();
const choose = async (service: (typeof STREAMING_SERVICES)[number]) => {
const mine = me?.services ?? [];
const save = async (services: StreamingService[], preferredService: StreamingService | null) => {
try {
setMe(await api.updateMe({ preferredService: service }));
setMe(await api.updateMe({ services: services.length ? services : null, preferredService }));
} catch (err) {
showError(err);
}
};
const toggle = (s: StreamingService) => {
const services = mine.includes(s) ? mine.filter((x) => x !== s) : [...mine, s];
// The main service has to be one you use; fall back to the first one left.
const main = me?.preferredService && services.includes(me.preferredService) ? me.preferredService : (services[0] ?? null);
save(services, main);
};
return (
<Card>
<Heading>Open songs in</Heading>
<Heading>Your music services</Heading>
<Body muted style={styles.small}>
Songs only show buttons for the ones you pick.
</Body>
<Row>
{STREAMING_SERVICES.map((s) => (
<Chip key={s} label={SERVICE_LABELS[s]} selected={me?.preferredService === s} onPress={() => choose(s)} />
<Chip key={s} label={SERVICE_LABELS[s]} selected={mine.includes(s)} onPress={() => toggle(s)} />
))}
</Row>
{mine.length > 1 && (
<>
<Heading>Open songs in</Heading>
<Row>
{mine.map((s) => (
<Chip key={s} label={SERVICE_LABELS[s]} selected={me?.preferredService === s} onPress={() => save(mine, s)} />
))}
</Row>
</>
)}
</Card>
);
}
+1 -1
View File
@@ -22,7 +22,7 @@ export default function ListenAppStep() {
if (!app) return;
setBusy(true);
try {
if (app.service) setMe(await api.updateMe({ preferredService: app.service }));
if (app.service) setMe(await api.updateMe({ preferredService: app.service, services: [app.service] }));
router.push({ pathname: '/onboarding/share', params: { app: app.id } });
} catch (err) {
showError(err);