'use client'; import { AnimatePresence, motion } from 'motion/react'; import Link from 'next/link'; import useSWR from 'swr'; import { sortFeed, type FeedItemDTO, type FollowListDTO, type ProfileDTO } from '@musicshare/shared'; import { Avatar } from '@/components/Avatar'; import { Equalizer } from '@/components/Equalizer'; import { NowPlayingCard } from '@/components/NowPlayingCard'; import { SharingControls } from '@/components/SharingControls'; import { api, fetcher, useMe } from '@/lib/api'; import { useRealtime } from '@/lib/useRealtime'; export default function Home() { const { me, isLoading, loggedOut } = useMe(); if (isLoading) return null; if (loggedOut || !me) return ; return ; } function Feed() { const { me } = useMe(); const { data: feed, mutate } = useSWR('/feed', fetcher); // Your own profile, for the "You" card. Loading it also marks you as watched, so your updates arrive quickly. const { data: mine, mutate: mutateMine } = useSWR(me ? `/users/${me.username}` : null, fetcher); // Everyone you follow; the feed only has the ones who've played something. const { data: following } = useSWR(me ? `/users/${me.username}/following` : null, fetcher); const inFeed = new Set(feed?.map((n) => n.user.id)); const quiet = following?.users.filter((u) => !inFeed.has(u.id)) ?? []; useRealtime(true, (msg) => { if (msg.type !== 'now_playing') return; if (msg.data.user.id === me?.id) { if (mine) mutateMine({ ...mine, nowPlaying: msg.data }, { revalidate: false }); return; } mutate( (current = []) => { const existing = current.find((n) => n.user.id === msg.data.user.id); const item = { ...msg.data, pinnedAt: existing?.pinnedAt ?? null }; return sortFeed([item, ...current.filter((n) => n.user.id !== msg.data.user.id)]); }, { revalidate: false }, ); }); const togglePin = async (item: FeedItemDTO) => { const pinnedAt = item.pinnedAt ? null : new Date().toISOString(); // optimistic: reorder immediately, roll back if the server refuses (e.g. pin limit) const previous = feed; mutate(sortFeed((feed ?? []).map((n) => (n.user.id === item.user.id ? { ...n, pinnedAt } : n))), { revalidate: false }); try { await api(`/users/${item.user.username}/pin`, { method: pinnedAt ? 'PUT' : 'DELETE', body: pinnedAt ? {} : undefined }); } catch (err) { mutate(previous, { revalidate: false }); alert((err as Error).message); } }; return (
{mine?.nowPlaying && (

You

)}

Friends listening

{!me?.preferredService && (

Pick your streaming service in Settings so songs open in the right app.

)} {feed?.length === 0 && (following?.users.length ? (

Nobody you follow has played anything yet. Their music will show up here live.

) : (

Nothing yet. Find friends, and their music will show up here live.

))} {/* Cards rise in on load and glide to new positions when someone pins or starts playing. */} {feed?.map((np, i) => ( togglePin(np)} /> ))} {quiet.length > 0 && (

Following ยท nothing played yet

{quiet.map((u) => ( {u.displayName ?? u.username} ))} {following?.nextCursor && me && ( See all )}
)}
); } function Landing() { return (

See what your friends are playing.

Share what you play on Spotify, Apple Music, YouTube Music, Plex and more. When a friend on Apple Music is playing something you like, one tap opens it in your app.

Create account Log in
); }