Create-account links for Last.fm and ListenBrainz, and Link Spotify for ListenBrainz
ListenBrainz accounts are MusicBrainz accounts, so its sign-up link goes to MusicBrainz. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
import { Linking } from 'react-native';
|
||||
import { mutate } from 'swr';
|
||||
import { SERVICE_LABELS } from '@musicshare/shared';
|
||||
import { SignInError, signInWithService } from '@/lib/connect';
|
||||
import { SignInError, openSignupPage, signInWithService } from '@/lib/connect';
|
||||
import { Button } from '../ui';
|
||||
import { ErrorText, SetupActions, SetupHeader, type SetupProps } from './common';
|
||||
|
||||
@@ -57,7 +56,7 @@ export function ServiceSignInSetup({
|
||||
/>
|
||||
<ErrorText>{error}</ErrorText>
|
||||
<SetupActions primary="Sign in with Last.fm" loading={busy} onPrimary={run} onSkip={onDone} skipLabel={skipLabel} />
|
||||
<Button small title="New to Last.fm? Create an account" onPress={() => Linking.openURL('https://www.last.fm/join')} />
|
||||
<Button small title="New to Last.fm? Create an account" onPress={() => openSignupPage('lastfm')} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { useState } from 'react';
|
||||
import { Linking, Pressable, StyleSheet, Text, View } from 'react-native';
|
||||
import { Pressable, StyleSheet, Text, View } from 'react-native';
|
||||
import useSWR, { mutate } from 'swr';
|
||||
import type { ConnectionDTO } from '@musicshare/shared';
|
||||
import { api } from '@/lib/api';
|
||||
import { SignInError, openSpotifyLinkPage, signInWithService } from '@/lib/connect';
|
||||
import { SignInError, openSignupPage, openSpotifyLinkPage, signInWithService } from '@/lib/connect';
|
||||
import { successHaptic } from '@/lib/haptics';
|
||||
import { colors, radius, space } from '@/lib/theme';
|
||||
import { Body, Button, Field } from '../ui';
|
||||
@@ -108,7 +108,7 @@ export function SpotifySetup({ onDone, skipLabel }: SetupProps) {
|
||||
onPress={() => setVia('listenbrainz')}
|
||||
title="ListenBrainz"
|
||||
badge="Open source"
|
||||
detail="Free and run by a nonprofit. Enter your ListenBrainz username."
|
||||
detail="Free and run by a nonprofit. Enter your ListenBrainz username, then approve Spotify on ListenBrainz."
|
||||
/>
|
||||
|
||||
{via === 'listenbrainz' && (
|
||||
@@ -123,9 +123,16 @@ export function SpotifySetup({ onDone, skipLabel }: SetupProps) {
|
||||
)}
|
||||
<Button title={skipLabel ?? 'Not now'} onPress={onDone} />
|
||||
</View>
|
||||
<Body muted style={styles.small} onPress={() => Linking.openURL(via === 'listenbrainz' ? 'https://listenbrainz.org/login/' : 'https://www.last.fm/join')}>
|
||||
No account yet? Create one free on {via === 'listenbrainz' ? 'ListenBrainz' : 'Last.fm'} first.
|
||||
{via && (
|
||||
<View style={{ gap: space.xs }}>
|
||||
<Button small title={`No account? Create one on ${via === 'listenbrainz' ? 'MusicBrainz' : 'Last.fm'}`} onPress={() => openSignupPage(via)} />
|
||||
{via === 'listenbrainz' && (
|
||||
<Body muted style={styles.small}>
|
||||
ListenBrainz uses MusicBrainz accounts. After creating one, sign in to ListenBrainz once, then come back.
|
||||
</Body>
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as Linking from 'expo-linking';
|
||||
import * as WebBrowser from 'expo-web-browser';
|
||||
import { SPOTIFY_LINK_PAGES } from '@musicshare/shared';
|
||||
import { SIGNUP_PAGES, SPOTIFY_LINK_PAGES } from '@musicshare/shared';
|
||||
import { api } from './api';
|
||||
|
||||
export type SignInResult = 'connected' | 'cancelled';
|
||||
@@ -25,3 +25,6 @@ export async function signInWithService(provider: 'plex' | 'lastfm'): Promise<Si
|
||||
/** Where users approve "Spotify Scrobbling" (Last.fm) or the Spotify link (ListenBrainz). */
|
||||
export const openSpotifyLinkPage = (on: keyof typeof SPOTIFY_LINK_PAGES = 'lastfm') =>
|
||||
WebBrowser.openBrowserAsync(SPOTIFY_LINK_PAGES[on]);
|
||||
|
||||
/** Their sign-up page, in the in-app browser (ListenBrainz accounts start on MusicBrainz). */
|
||||
export const openSignupPage = (service: keyof typeof SIGNUP_PAGES) => WebBrowser.openBrowserAsync(SIGNUP_PAGES[service]);
|
||||
|
||||
@@ -6,6 +6,7 @@ import { Suspense, useEffect, useRef, useState } from 'react';
|
||||
import useSWR from 'swr';
|
||||
import {
|
||||
SERVICE_LABELS,
|
||||
SIGNUP_PAGES,
|
||||
SPOTIFY_LINK_PAGES,
|
||||
STREAMING_SERVICES,
|
||||
isQuietScrobbler,
|
||||
@@ -317,14 +318,21 @@ function Connections() {
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{!byProvider.has(p) && (
|
||||
<div className="muted small">
|
||||
No account?{' '}
|
||||
<a href={SIGNUP_PAGES[p]} target="_blank" rel="noreferrer">
|
||||
Create one free on {p === 'lastfm' ? 'Last.fm' : 'MusicBrainz'}
|
||||
</a>
|
||||
{p === 'listenbrainz' ? ', then sign in to ListenBrainz once (it uses MusicBrainz accounts).' : '.'}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{byProvider.has(p) ? (
|
||||
<div className="row">
|
||||
{p === 'lastfm' && (
|
||||
<a className="btn" href="https://www.last.fm/settings/applications" target="_blank" rel="noreferrer">
|
||||
<a className="btn" href={SPOTIFY_LINK_PAGES[p]} target="_blank" rel="noreferrer">
|
||||
Link Spotify
|
||||
</a>
|
||||
)}
|
||||
<button className="btn" onClick={() => disconnect(p)}>
|
||||
Disconnect
|
||||
</button>
|
||||
|
||||
@@ -103,6 +103,15 @@ export const SPOTIFY_LINK_PAGES = {
|
||||
listenbrainz: 'https://listenbrainz.org/settings/music-services/details/',
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* Where to make a free account (neither lets other apps create one). ListenBrainz accounts are
|
||||
* MusicBrainz accounts: register there, then sign in to ListenBrainz once to start it.
|
||||
*/
|
||||
export const SIGNUP_PAGES = {
|
||||
lastfm: 'https://www.last.fm/join',
|
||||
listenbrainz: 'https://musicbrainz.org/register',
|
||||
} as const;
|
||||
|
||||
const QUIET_AFTER_MS = 7 * 86_400_000;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user