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)

StatelessWidgetConsumerWidget

The build method signature changed from (BuildContext context) to (BuildContext context, WidgetRef ref), enabling reactive provider watching inside the widget tree.

Three providers watched:

ProviderSourceUsed for
totalUnreadChatCountProviderchat_notifier.dartChat tab badge
unreadNotificationsCountProvidernotification_notifier.dartHome badge input
pendingRequestsProvidersocial_notifier.dartHome 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 Container positioned top: -5, right: -7 relative to the icon
  • White 1.5px border 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.

StateButton colorLabelTappable
noneCoral”Aggiungi”✓ (sends request)
pendingGrey”Richiesta inviata”
friendsGreen”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.