The feed only listed people who had played something, so following someone who hadn't connected a service yet looked like it did nothing. Under the feed, a "Following" row now shows everyone else you follow, linking to their profiles, and the empty message says why it's empty. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MzFywujuH9TiuXbr9vjoX8
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
import { router } from 'expo-router';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { RefreshControl, StyleSheet, Text, View } from 'react-native';
|
||||
import { Pressable, RefreshControl, ScrollView, StyleSheet, Text, View } from 'react-native';
|
||||
import Animated, { FadeInDown, LinearTransition } from 'react-native-reanimated';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import useSWR from 'swr';
|
||||
import { sortFeed, type ConnectionDTO, type FeedItemDTO, type ProfileDTO } from '@musicshare/shared';
|
||||
import { sortFeed, type ConnectionDTO, type FeedItemDTO, type FollowListDTO, type ProfileDTO } from '@musicshare/shared';
|
||||
import { AmbientBackground } from '@/components/AmbientBackground';
|
||||
import { Avatar } from '@/components/Avatar';
|
||||
import { NowPlayingCard } from '@/components/NowPlayingCard';
|
||||
import { RelinkReminder } from '@/components/RelinkReminder';
|
||||
import { SharingControls } from '@/components/SharingControls';
|
||||
@@ -24,6 +25,10 @@ export default function FeedScreen() {
|
||||
const { data: feed, mutate, isLoading } = useSWR<FeedItemDTO[]>('/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<ProfileDTO>(me ? `/users/${me.username}` : null);
|
||||
// Everyone you follow; the feed only has the ones who've played something.
|
||||
const { data: following, mutate: mutateFollowing } = useSWR<FollowListDTO>(me ? `/users/${me.username}/following` : null);
|
||||
const inFeed = new Set(feed?.map((n) => n.user.id));
|
||||
const quiet = following?.users.filter((u) => !inFeed.has(u.id)) ?? [];
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
|
||||
const reader = useReader();
|
||||
@@ -67,7 +72,7 @@ export default function FeedScreen() {
|
||||
|
||||
const refresh = async () => {
|
||||
setRefreshing(true);
|
||||
await Promise.all([mutate(), mutateMine()]).catch(() => {});
|
||||
await Promise.all([mutate(), mutateMine(), mutateFollowing()]).catch(() => {});
|
||||
setRefreshing(false);
|
||||
};
|
||||
|
||||
@@ -115,11 +120,37 @@ export default function FeedScreen() {
|
||||
ListEmptyComponent={
|
||||
isLoading ? null : (
|
||||
<Card>
|
||||
<Body muted>Nothing yet. Follow some friends and their music will show up here live.</Body>
|
||||
<Body muted>
|
||||
{following?.users.length
|
||||
? 'Nobody you follow has played anything yet. Their music will show up here live.'
|
||||
: 'Nothing yet. Follow some friends and their music will show up here live.'}
|
||||
</Body>
|
||||
<Button small variant="primary" title="Find friends" onPress={() => router.push('/search')} style={{ alignSelf: 'flex-start' }} />
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
ListFooterComponent={
|
||||
quiet.length > 0 ? (
|
||||
<View style={{ gap: space.sm, marginTop: space.md }}>
|
||||
<Text style={styles.sectionLabel}>FOLLOWING · NOTHING PLAYED YET</Text>
|
||||
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.quiet}>
|
||||
{quiet.map((u) => (
|
||||
<Pressable key={u.id} onPress={() => router.push(`/u/${u.username}`)} style={styles.quietPerson} accessibilityLabel={u.displayName ?? u.username}>
|
||||
<Avatar user={u} size={52} />
|
||||
<Text style={styles.quietName} numberOfLines={1}>
|
||||
{u.displayName ?? u.username}
|
||||
</Text>
|
||||
</Pressable>
|
||||
))}
|
||||
{following?.nextCursor && me && (
|
||||
<Pressable onPress={() => router.push(`/u/${me.username}/following`)} style={[styles.quietPerson, { justifyContent: 'center' }]}>
|
||||
<Text style={[styles.quietName, { color: colors.muted }]}>See all</Text>
|
||||
</Pressable>
|
||||
)}
|
||||
</ScrollView>
|
||||
</View>
|
||||
) : null
|
||||
}
|
||||
renderItem={({ item, index }) => (
|
||||
<Animated.View entering={FadeInDown.delay(Math.min(index, 8) * 60).springify().damping(16)}>
|
||||
<NowPlayingCard
|
||||
@@ -140,4 +171,7 @@ const styles = StyleSheet.create({
|
||||
list: { padding: space.lg, gap: space.md, paddingBottom: space.xl * 3 },
|
||||
header: { gap: space.md, marginBottom: space.xs },
|
||||
sectionLabel: { color: colors.muted, fontSize: 12, fontWeight: '700', letterSpacing: 0.8 },
|
||||
quiet: { gap: space.lg, paddingVertical: space.xs },
|
||||
quietPerson: { width: 64, alignItems: 'center', gap: 4 },
|
||||
quietName: { color: colors.text, fontSize: 12, textAlign: 'center' },
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user