Friends Activity Feed
Branch: feat/friends-activity-feed
Merged into: develop
Date: March 2026
Overview
Added a “Cosa fanno gli amici” (What your friends are doing) section to the Social screen. It shows a horizontal carousel of upcoming events that the user’s friends have marked as “Going”, giving users social context and a discovery mechanism through their social graph.
This completes the roadmap item: “View friends’ attending events” (Phase 1 MVP).
Why It Was Built
Without this feature, the social graph was invisible from the event discovery perspective. Users had no way to know which events their friends were attending, removing one of the most powerful social discovery mechanisms (seeing where people you trust are going). The friendsGoing field already existed on the Event model but was never populated or surfaced in the UI.
What Changed
API Layer (event_api_service.dart)
Added getFriendsEvents(List<String> friendIds, {int limit = 20}):
event_attendees (user_id IN friendIds, status = 'going', event.start_date >= now)
└── profiles(*) ← the attending friend's profile
└── events(*, profiles!events_organizer_id_fkey(*)) ← the event + organizer
A grouping step merges rows so multiple friends attending the same event are combined into a single Event with all friends in its friendsGoing list, rather than showing duplicate cards.
The organizer join key is normalized to profiles before passing to _mapSupabaseEventToEvent, matching the existing pattern used by getInterestedEvents.
Repository (event_repository.dart)
- Added:
Future<List<Event>> getFriendsEvents(List<String> friendIds) => _api.getFriendsEvents(friendIds);
State & Logic (event_notifier.dart)
EventState gained a new friendsActivity: List<Event> field.
EventNotifier gained loadFriendsActivity(List<String> friendIds) — fetches friends events and stores in state.
UI (friends_screen.dart)
initState loading sequence:
crewNotifier.fetchActiveCrews()(unchanged)await socialNotifier.loadFriends()— ensures friend list is populated- Extract friend IDs from state, call
eventNotifier.loadFriendsActivity(friendIds)
The sequential await on step 2 is necessary because step 3 depends on the friend IDs. Without this ordering, loadFriendsActivity would be called with an empty list.
New section: _buildFriendsActivitySection()
- Hidden entirely when
friends.isEmpty(first-time users with no social graph) - Shows a compact empty-state text when
friendsActivity.isEmpty(friends exist but none are going to upcoming events) - Otherwise renders a
SizedBox(height: 180)horizontal scroll of_buildFriendEventCardwidgets
Event card design:
200×180rounded card with event image or a deterministic gradient (derived from event ID hash, cycling through 4 coral/purple/teal/orange palettes)- Title (2 lines, ellipsis), date in Italian short format (
lun 23 mar) - Friend avatar stack: up to 3 overlapping
ProfileAvatarcircles (radius 10) + label showing the first friend’s name and “+N others” if applicable
Navigation: tapping a card navigates to /events/${event.id}.
Architecture Notes
The friends activity query relies on two sequential Supabase calls (one from social notifier to fetch friends, one from event notifier to fetch their events). This two-step pattern avoids a complex RPC while keeping each service focused on its domain. If the friends list is empty (e.g., on first launch), the second call is skipped entirely to avoid wasted queries.