Bottom Nav Badges
Branch: feat/bottom-nav-badges
Merged into: develop
Date: March 2026
Overview
FlowBottomNav was previously a StatelessWidget with no awareness of app state. This feature upgraded it to a ConsumerWidget that reactively watches three providers and displays badge counts on the Home and Chat tabs — giving users at-a-glance awareness of pending activity without opening each section.
Why It Was Built
Badge counts on navigation bars are a standard affordance for driving re-engagement. Without them, users had no visual signal that someone sent them a friend request or that a new message arrived. The underlying providers (unreadNotificationsCountProvider, totalUnreadChatCountProvider, pendingRequestsProvider) were already emitting counts — the only missing piece was surfacing them in the nav bar.
What Changed
Widget Upgrade (flow_bottom_nav.dart)
StatelessWidget → ConsumerWidget
The build method signature changed from (BuildContext context) to (BuildContext context, WidgetRef ref), enabling reactive provider watching inside the widget tree.
Three providers watched:
| Provider | Source | Used for |
|---|---|---|
totalUnreadChatCountProvider | chat_notifier.dart | Chat tab badge |
unreadNotificationsCountProvider | notification_notifier.dart | Home badge input |
pendingRequestsProvider | social_notifier.dart | Home badge input |
Home badge aggregation:
homeBadge = unreadNotifications + pendingFriendRequests
Both types of actionable activity (new notifications + pending friend requests) are combined into a single badge on the Home tab, since both resolve in the Notifications screen.
Badge widget:
- Coral
Containerpositionedtop: -5, right: -7relative to the icon - White
1.5pxborder creates the “floating pill” effect against any background color - Text: white,
9px,FontWeight.w800; capped at'99+'for large counts - Hidden entirely when
badge == 0(no empty badge ring shown)
Public Profile Screen (public_profile_screen.dart)
As a companion change, the “Aggiungi amico” button on the public profile now reflects real friendship state:
enum _FriendStatus { none, pending, friends } — local enum to track the three possible states.
On initState, the notifier loads both friends and pendingRequests, then _updateFriendStatus() checks if widget.userId appears in either list.
| State | Button color | Label | Tappable |
|---|---|---|---|
none | Coral | ”Aggiungi” | ✓ (sends request) |
pending | Grey | ”Richiesta inviata” | ✗ |
friends | Green | ”Amici ✓” | ✗ |
After sending a request the state transitions to pending immediately (optimistic), avoiding a round-trip to confirm.
Architecture Notes
The badge system requires no new backend calls — it derives entirely from state that other screens already fetch. pendingRequestsProvider is a selector over socialNotifierProvider, so it only rebuilds badge-consuming widgets when the pending count actually changes, not on every social state update.