import { router } from 'expo-router'; import { useEffect, useState } from 'react'; import { FlatList, RefreshControl, StyleSheet, Text, View } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import useSWR from 'swr'; import { sortFeed, type FeedItemDTO, type ProfileDTO } from '@musicshare/shared'; import { NowPlayingCard } from '@/components/NowPlayingCard'; import { SharingControls } from '@/components/SharingControls'; import { Body, Button, Card, Title } from '@/components/ui'; import { api } from '@/lib/api'; import { showError } from '@/lib/errors'; import { shouldOfferSetup, useReader } from '@/lib/nowPlayingReader'; import { useRealtime } from '@/lib/useRealtime'; import { useSession } from '@/lib/session'; import { colors, space } from '@/lib/theme'; export default function FeedScreen() { const { me } = useSession(); const { data: feed, mutate, isLoading } = useSWR('/feed'); // 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); const [refreshing, setRefreshing] = useState(false); const reader = useReader(); // First run on Android: open the one-tap setup once (deferred so navigation has mounted). useEffect(() => { const timer = setTimeout(() => { shouldOfferSetup().then((offer) => offer && router.push('/share-setup')); }, 400); return () => clearTimeout(timer); }, []); 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); return sortFeed([{ ...msg.data, pinnedAt: existing?.pinnedAt ?? null }, ...current.filter((n) => n !== existing)]); }, { revalidate: false }, ); }); const togglePin = async (item: FeedItemDTO) => { const pinnedAt = item.pinnedAt ? null : new Date().toISOString(); const previous = feed; mutate(sortFeed((feed ?? []).map((n) => (n.user.id === item.user.id ? { ...n, pinnedAt } : n))), { revalidate: false }); try { await (pinnedAt ? api.pin(item.user.username) : api.unpin(item.user.username)); } catch (err) { mutate(previous, { revalidate: false }); showError(err, "Couldn't pin"); } }; const refresh = async () => { setRefreshing(true); await Promise.all([mutate(), mutateMine()]).catch(() => {}); setRefreshing(false); }; return ( item.user.id} contentContainerStyle={styles.list} refreshControl={} ListHeaderComponent={ {reader.available && !reader.granted && ( Share what you’re playing in Spotify, YouTube Music and other apps. One tap, no accounts.