Friend Request Management

Branch: feat/friend-request-management Merged into: develop Date: March 2026

Overview

Wired up the complete friend request accept/reject flow. FriendService.acceptFriendRequest() existed in the codebase but was unreachable from any UI — a classic case of “dead code by incomplete wiring”. This feature completes the chain from service all the way to inline Accept/Reject buttons displayed in the Notifications screen.

Why It Was Built

The MVP roadmap lists “Friend requests and acceptance” as a core social feature for Phase 1. Without the ability to accept or decline requests, the social graph would never grow — users could send requests but the recipient had no mechanism to respond. The backend table (friendships with status = 'pending') was already in place.

What Changed

Service (friend_service.dart)

Two new methods added:

getPendingRequests() Queries friendships where friend_id = me and status = 'pending', joining with profiles!friendships_user_id_fkey to return full User objects for each sender.

rejectFriendRequest(userId) Deletes the matching friendships row where user_id = sender and friend_id = me.

The existing acceptFriendRequest() was also cleaned up (whitespace only).

Repository (social_repository.dart)

Exposed all three methods as thin wrappers:

  • getPendingRequests()
  • acceptFriendRequest(userId)
  • rejectFriendRequest(userId)

State & Logic (social_notifier.dart)

SocialState gained a new pendingRequests: List<User> field.

SocialNotifier gained three new methods:

MethodBehavior
loadPendingRequests()Fetches pending requests and stores in state
acceptFriendRequest(userId)Calls repo, then optimistically removes from pendingRequests and prepends to friends
rejectFriendRequest(userId)Calls repo, then optimistically removes from pendingRequests

A new pendingRequestsProvider selector was added for convenient widget consumption.

UI (notifications_screen.dart)

  • Added imports for SocialNotifier, User, ProfileAvatar
  • On initState: loads pending requests alongside notifications
  • build now watches pendingRequestsProvider
  • The ListView.builder was replaced with a CustomScrollView containing two SliverLists:
    1. Friend requests section (only rendered when pendingRequests.isNotEmpty) — shows a section header with a coral count badge, followed by one _buildFriendRequestCard per request
    2. Regular notifications section — unchanged list of notification items
  • Pull-to-refresh now refreshes both lists simultaneously

Friend Request Card Design

Each card shows:

  • Avatar (tappable → navigates to /user/:id)
  • Display name + @username
  • “Rifiuta” outlined button (grey border) — removes request
  • “Accetta” filled button (coral) — accepts and shows a snackbar confirmation

Optimistic State Updates

Both accept and reject update the UI immediately before the server confirms:

  • Accept: user disappears from requests, appears in friends list
  • Reject: user disappears from requests

If the server fails, state.error is set, but the UI has already moved. For social actions with near-zero failure rates, this trade-off prioritises perceived performance.