feat: enhance routing and connectivity handling
- Added a new route for connection issues, allowing users to navigate to a dedicated page when the server is unreachable. - Updated the RouterNotifier to manage navigation based on server connectivity status and authentication state. - Improved the handling of offline scenarios by integrating connectivity checks into the routing logic. - Enhanced localization support for connection issue messages in multiple languages. - Refactored the OfflineIndicator widget to streamline the display of connectivity status without unnecessary complexity.
This commit is contained in:
@@ -535,13 +535,13 @@ class ConduitThemeExtension extends ThemeExtension<ConduitThemeExtension> {
|
||||
buttonDisabledText: AppTheme.neutral400,
|
||||
|
||||
// Status and feedback colors - Enhanced visibility
|
||||
success: Color(0xFF22C55E),
|
||||
success: Color(0xFF34D399),
|
||||
successBackground: Color(0xFF14532D),
|
||||
error: Color(0xFFEF4444),
|
||||
error: Color(0xFFFCA5A5),
|
||||
errorBackground: Color(0xFF7F1D1D),
|
||||
warning: Color(0xFFF59E0B),
|
||||
warningBackground: Color(0xFF7C2D12),
|
||||
info: Color(0xFF38BDF8),
|
||||
warning: Color(0xFFFBBF24),
|
||||
warningBackground: Color(0xFF451A03),
|
||||
info: Color(0xFF93C5FD),
|
||||
infoBackground: Color(0xFF0C4A6E),
|
||||
|
||||
// Navigation and UI element colors - Enhanced contrast
|
||||
@@ -549,7 +549,7 @@ class ConduitThemeExtension extends ThemeExtension<ConduitThemeExtension> {
|
||||
navigationBackground: Color(0xFF0A0D0C),
|
||||
navigationSelected: AppTheme.brandPrimary,
|
||||
navigationUnselected: AppTheme.neutral300,
|
||||
navigationSelectedBackground: AppTheme.brandPrimary,
|
||||
navigationSelectedBackground: Color(0xFF312E81),
|
||||
|
||||
// Loading and animation colors - Enhanced visibility
|
||||
shimmerBase: Color(0xFF121514),
|
||||
@@ -660,21 +660,21 @@ class ConduitThemeExtension extends ThemeExtension<ConduitThemeExtension> {
|
||||
buttonDisabledText: AppTheme.neutral500,
|
||||
|
||||
// Status and feedback colors - Enhanced visibility
|
||||
success: Color(0xFF16A34A),
|
||||
successBackground: Color(0xFFEFFBF3),
|
||||
error: Color(0xFFDC2626),
|
||||
errorBackground: Color(0xFFFDECEC),
|
||||
warning: Color(0xFFD97706),
|
||||
warningBackground: Color(0xFFFEF6E7),
|
||||
info: Color(0xFF0284C7),
|
||||
infoBackground: Color(0xFFE8F4FD),
|
||||
success: Color(0xFF166534),
|
||||
successBackground: Color(0xFFECFDF3),
|
||||
error: Color(0xFFB91C1C),
|
||||
errorBackground: Color(0xFFFEE2E2),
|
||||
warning: Color(0xFF92400E),
|
||||
warningBackground: Color(0xFFFEF3C7),
|
||||
info: Color(0xFF1D4ED8),
|
||||
infoBackground: Color(0xFFDBEAFE),
|
||||
|
||||
// Navigation and UI element colors - Enhanced contrast
|
||||
dividerColor: AppTheme.neutral100,
|
||||
navigationBackground: AppTheme.neutral50,
|
||||
navigationSelected: AppTheme.brandPrimary,
|
||||
navigationUnselected: AppTheme.neutral600,
|
||||
navigationSelectedBackground: AppTheme.brandPrimary,
|
||||
navigationSelectedBackground: Color(0xFFE0E7FF),
|
||||
|
||||
// Loading and animation colors - Enhanced visibility
|
||||
shimmerBase: Color(0xFFF3F4F6),
|
||||
|
||||
@@ -15,13 +15,8 @@ part 'offline_indicator.g.dart';
|
||||
|
||||
class OfflineIndicator extends ConsumerWidget {
|
||||
final Widget child;
|
||||
final bool showBanner;
|
||||
|
||||
const OfflineIndicator({
|
||||
super.key,
|
||||
required this.child,
|
||||
this.showBanner = true,
|
||||
});
|
||||
const OfflineIndicator({super.key, required this.child});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
@@ -33,26 +28,22 @@ class OfflineIndicator extends ConsumerWidget {
|
||||
orElse: () => false,
|
||||
);
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
child,
|
||||
if (showBanner)
|
||||
connectivityStatus.when(
|
||||
data: (status) {
|
||||
if (status == ConnectivityStatus.offline || socketOffline) {
|
||||
return _OfflineBanner();
|
||||
}
|
||||
// Announce back-online briefly if we were previously offline
|
||||
if (wasOffline) {
|
||||
return const _BackOnlineToast();
|
||||
}
|
||||
return const SizedBox.shrink();
|
||||
},
|
||||
loading: () => const SizedBox.shrink(),
|
||||
error: (_, _) => _OfflineBanner(),
|
||||
),
|
||||
],
|
||||
final overlay = connectivityStatus.when(
|
||||
data: (status) {
|
||||
if ((status == ConnectivityStatus.offline || socketOffline) &&
|
||||
!wasOffline) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
if (wasOffline) {
|
||||
return const _BackOnlineToast();
|
||||
}
|
||||
return const SizedBox.shrink();
|
||||
},
|
||||
loading: () => const SizedBox.shrink(),
|
||||
error: (unusedError, unusedStackTrace) => const SizedBox.shrink(),
|
||||
);
|
||||
|
||||
return Stack(children: [child, overlay]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,65 +128,6 @@ class _BackOnlineToast extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class _OfflineBanner extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Positioned(
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: SafeArea(
|
||||
bottom: false,
|
||||
child:
|
||||
Semantics(
|
||||
container: true,
|
||||
liveRegion: true,
|
||||
label: AppLocalizations.of(context)!.offlineBanner,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: Spacing.md,
|
||||
vertical: Spacing.xs,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: context.conduitTheme.warning,
|
||||
boxShadow: ConduitShadows.low,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
Platform.isIOS
|
||||
? CupertinoIcons.wifi_slash
|
||||
: Icons.wifi_off,
|
||||
color: context.conduitTheme.textInverse,
|
||||
size: AppTypography.headlineMedium,
|
||||
),
|
||||
const SizedBox(width: Spacing.xs),
|
||||
Expanded(
|
||||
child: Text(
|
||||
AppLocalizations.of(context)!.offlineBanner,
|
||||
style: TextStyle(
|
||||
color: context.conduitTheme.textInverse,
|
||||
fontSize: AppTypography.labelLarge,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
.animate(onPlay: (controller) => controller.forward())
|
||||
.slideY(
|
||||
begin: -1,
|
||||
end: 0,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeOutCubic,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Inline offline indicator for specific features
|
||||
class InlineOfflineIndicator extends ConsumerWidget {
|
||||
final String message;
|
||||
@@ -217,16 +149,20 @@ class InlineOfflineIndicator extends ConsumerWidget {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
final theme = context.conduitTheme;
|
||||
final surfaceColor = backgroundColor ?? theme.warningBackground;
|
||||
final borderAlpha = Theme.of(context).brightness == Brightness.dark
|
||||
? 0.45
|
||||
: 0.3;
|
||||
|
||||
return Container(
|
||||
margin: const EdgeInsets.all(Spacing.md),
|
||||
padding: const EdgeInsets.all(Spacing.md),
|
||||
decoration: BoxDecoration(
|
||||
color:
|
||||
backgroundColor ??
|
||||
context.conduitTheme.warning.withValues(alpha: 0.1),
|
||||
color: surfaceColor,
|
||||
borderRadius: BorderRadius.circular(AppBorderRadius.md),
|
||||
border: Border.all(
|
||||
color: context.conduitTheme.warning.withValues(alpha: 0.3),
|
||||
color: theme.warning.withValues(alpha: borderAlpha),
|
||||
width: BorderWidth.regular,
|
||||
),
|
||||
),
|
||||
@@ -235,7 +171,7 @@ class InlineOfflineIndicator extends ConsumerWidget {
|
||||
Icon(
|
||||
icon ??
|
||||
(Platform.isIOS ? CupertinoIcons.wifi_slash : Icons.wifi_off),
|
||||
color: context.conduitTheme.warning,
|
||||
color: theme.warning,
|
||||
size: Spacing.lg,
|
||||
),
|
||||
const SizedBox(width: Spacing.xs),
|
||||
@@ -245,7 +181,7 @@ class InlineOfflineIndicator extends ConsumerWidget {
|
||||
? message
|
||||
: AppLocalizations.of(context)!.featureRequiresInternet,
|
||||
style: TextStyle(
|
||||
color: context.conduitTheme.warning,
|
||||
color: theme.warning,
|
||||
fontSize: AppTypography.labelLarge,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
@@ -299,16 +235,22 @@ class ChatOfflineOverlay extends ConsumerWidget {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
final theme = context.conduitTheme;
|
||||
final surfaceColor = theme.warningBackground;
|
||||
final borderAlpha = Theme.of(context).brightness == Brightness.dark
|
||||
? 0.5
|
||||
: 0.35;
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: Spacing.md,
|
||||
vertical: Spacing.sm,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: context.conduitTheme.warning.withValues(alpha: 0.2),
|
||||
color: surfaceColor,
|
||||
border: Border(
|
||||
top: BorderSide(
|
||||
color: context.conduitTheme.warning.withValues(alpha: 0.5),
|
||||
color: theme.warning.withValues(alpha: borderAlpha),
|
||||
width: BorderWidth.regular,
|
||||
),
|
||||
),
|
||||
@@ -318,14 +260,14 @@ class ChatOfflineOverlay extends ConsumerWidget {
|
||||
children: [
|
||||
Icon(
|
||||
Platform.isIOS ? CupertinoIcons.wifi_slash : Icons.wifi_off,
|
||||
color: context.conduitTheme.warning,
|
||||
color: theme.warning,
|
||||
size: Spacing.md,
|
||||
),
|
||||
const SizedBox(width: Spacing.sm),
|
||||
Text(
|
||||
AppLocalizations.of(context)!.messagesWillSendWhenOnline,
|
||||
style: TextStyle(
|
||||
color: context.conduitTheme.warning,
|
||||
color: theme.warning,
|
||||
fontSize: AppTypography.bodySmall,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user