worldhopper/lib/widgets/worldhopper_app_bar.dart
Felipe M. 7d5c854dc9 feat: i18n (#2)
Reviewed-on: #2
Co-authored-by: Felipe M. <me@fmartingr.com>
Co-committed-by: Felipe M. <me@fmartingr.com>
2026-02-12 22:41:22 +01:00

113 lines
3.3 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:worldhopper/l10n/app_localizations.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<Widget>? 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 = <Widget>[
if (isOffline)
Padding(
padding: const EdgeInsets.only(right: 8),
child: Icon(
Icons.cloud_off,
color: Theme.of(context).colorScheme.error,
semanticLabel: AppLocalizations.of(context).offlineSemanticLabel,
),
),
...?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,
);
}
}