- "Share ↗" on every song (web and mobile): the phone's share sheet, or copy the link on desktop. Links go to a new song page, /t/<id>?from=you, with big artwork and open-in buttons for every service. - Server-rendered previews (Open Graph / Twitter cards) for song pages and profiles: title, who shared it or what they're playing, and the album art, avatar or logo. The web server fetches from the API over the compose network (INTERNAL_API_URL). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MzFywujuH9TiuXbr9vjoX8
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { parseProfileLink, profileUrl } from './links';
|
||||
import { parseProfileLink, profileUrl, trackUrl } from './links';
|
||||
|
||||
describe('profileUrl', () => {
|
||||
it('builds a website profile link, tolerating a trailing slash', () => {
|
||||
@@ -34,3 +34,10 @@ describe('parseProfileLink', () => {
|
||||
expect(parseProfileLink(text)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('trackUrl', () => {
|
||||
it('links to the song page, optionally saying who shared it', () => {
|
||||
expect(trackUrl('https://m.test/', 'abc')).toBe('https://m.test/t/abc');
|
||||
expect(trackUrl('https://m.test', 'abc', 'alice')).toBe('https://m.test/t/abc?from=alice');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,6 +29,15 @@ export function parseProfileLink(text: string): string | null {
|
||||
return match ? valid(decodeURIComponent(match[1]!)) : null;
|
||||
}
|
||||
|
||||
/** Shareable song page on the website, e.g. https://musicshare.app/t/<id>?from=alice */
|
||||
export function trackUrl(webBase: string, trackId: string, from?: string | null): string {
|
||||
const url = `${webBase.replace(/\/+$/, '')}/t/${encodeURIComponent(trackId)}`;
|
||||
return from ? `${url}?from=${encodeURIComponent(from)}` : url;
|
||||
}
|
||||
|
||||
/** What goes in the share sheet next to the link. */
|
||||
export const shareText = (track: { title: string; artist: string }) => `${track.title} by ${track.artist}`;
|
||||
|
||||
function valid(name: string): string | null {
|
||||
const username = name.toLowerCase();
|
||||
return USERNAME.test(username) ? username : null;
|
||||
|
||||
Reference in New Issue
Block a user