import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:worldhopper/providers/connectivity_provider.dart'; /// Custom AppBar that automatically shows offline indicator /// /// This widget wraps the standard AppBar and adds an offline icon /// (cloud_off) when the device is not connected to the internet. /// /// Usage: Replace standard AppBar with WorldhopperAppBar /// ```dart /// WorldhopperAppBar( /// title: Text('My Screen'), /// actions: [ /// IconButton(icon: Icon(Icons.search), onPressed: () {}), /// ], /// ) /// ``` class WorldhopperAppBar extends ConsumerWidget implements PreferredSizeWidget { final Widget? title; final List? actions; final Widget? leading; final bool automaticallyImplyLeading; final PreferredSizeWidget? bottom; final double? elevation; final Color? backgroundColor; final IconThemeData? iconTheme; final bool centerTitle; final double? leadingWidth; final TextStyle? titleTextStyle; final Color? foregroundColor; final Color? shadowColor; final Color? surfaceTintColor; final ShapeBorder? shape; final double? scrolledUnderElevation; final bool forceMaterialTransparency; final Clip? clipBehavior; const WorldhopperAppBar({ super.key, this.title, this.actions, this.leading, this.automaticallyImplyLeading = true, this.bottom, this.elevation, this.backgroundColor, this.iconTheme, this.centerTitle = false, this.leadingWidth, this.titleTextStyle, this.foregroundColor, this.shadowColor, this.surfaceTintColor, this.shape, this.scrolledUnderElevation, this.forceMaterialTransparency = false, this.clipBehavior, }); @override Size get preferredSize => Size.fromHeight( kToolbarHeight + (bottom?.preferredSize.height ?? 0.0), ); @override Widget build(BuildContext context, WidgetRef ref) { // Watch connectivity state final connectivityState = ref.watch(connectivityStateProvider); // Check if offline (default to online while loading) final isOffline = connectivityState.whenOrNull( data: (isOnline) => !isOnline, ) ?? false; // Build actions list with offline icon prepended if needed final effectiveActions = [ if (isOffline) Padding( padding: const EdgeInsets.only(right: 8), child: Icon( Icons.cloud_off, color: Theme.of(context).colorScheme.error, semanticLabel: 'Offline', ), ), ...?actions, ]; return AppBar( title: title, actions: effectiveActions.isEmpty ? null : effectiveActions, leading: leading, automaticallyImplyLeading: automaticallyImplyLeading, bottom: bottom, elevation: elevation, backgroundColor: backgroundColor, iconTheme: iconTheme, centerTitle: centerTitle, leadingWidth: leadingWidth, titleTextStyle: titleTextStyle, foregroundColor: foregroundColor, shadowColor: shadowColor, surfaceTintColor: surfaceTintColor, shape: shape, scrolledUnderElevation: scrolledUnderElevation, forceMaterialTransparency: forceMaterialTransparency, clipBehavior: clipBehavior, ); } }