From 43c7e5200be6de5262ec8418150fa82b32708381 Mon Sep 17 00:00:00 2001 From: cogwheel0 <172976095+cogwheel0@users.noreply.github.com> Date: Thu, 9 Oct 2025 16:07:34 +0530 Subject: [PATCH] refactor: remove offline indicator and streamline chat page logic - Deleted the OfflineIndicator widget and its associated logic to simplify the codebase. - Removed offline checks from the ChatPage, enhancing performance and reducing unnecessary rebuilds. - Adjusted the ChatsDrawer to change icon size for better visual consistency. - Cleaned up unused imports related to offline handling across multiple files. --- lib/features/chat/views/chat_page.dart | 16 -- .../navigation/widgets/chats_drawer.dart | 2 +- lib/main.dart | 3 +- lib/shared/widgets/offline_indicator.dart | 269 ------------------ 4 files changed, 2 insertions(+), 288 deletions(-) delete mode 100644 lib/shared/widgets/offline_indicator.dart diff --git a/lib/features/chat/views/chat_page.dart b/lib/features/chat/views/chat_page.dart index 0caeef2..80d6d53 100644 --- a/lib/features/chat/views/chat_page.dart +++ b/lib/features/chat/views/chat_page.dart @@ -29,8 +29,6 @@ import 'package:path/path.dart' as path; import '../../../shared/services/tasks/task_queue.dart'; import '../../tools/providers/tools_providers.dart'; import '../../navigation/widgets/chats_drawer.dart'; -import '../../../shared/widgets/offline_indicator.dart'; -import '../../../core/services/connectivity_service.dart'; import '../../../core/models/chat_message.dart'; import '../../../core/models/model.dart'; import '../../../shared/widgets/loading_states.dart'; @@ -334,13 +332,6 @@ class _ChatPageState extends ConsumerState { if (selectedModel == null) return; } - final isOnline = ref.read(isOnlineProvider); - final isReviewerMode = ref.read(reviewerModeProvider); - - if (!isOnline && !isReviewerMode) { - return; - } - try { // Get attached files and collect uploaded file IDs (including data URLs for images) final attachedFiles = ref.read(attachedFilesProvider); @@ -1039,8 +1030,6 @@ class _ChatPageState extends ConsumerState { Widget build(BuildContext context) { final theme = Theme.of(context); final l10n = AppLocalizations.of(context)!; - // Use select to watch only connectivity status to reduce rebuilds - final isOnline = ref.watch(isOnlineProvider.select((status) => status)); // Use select to watch only the selected model to reduce rebuilds final selectedModel = ref.watch( selectedModelProvider.select((model) => model), @@ -1537,9 +1526,6 @@ class _ChatPageState extends ConsumerState { // File attachments const FileAttachmentWidget(), - // Offline indicator - const ChatOfflineOverlay(), - // Modern Input (root matches input background including safe area) RepaintBoundary( child: MeasureSize( @@ -1551,8 +1537,6 @@ class _ChatPageState extends ConsumerState { } }, child: ModernChatInput( - enabled: - (isOnline || ref.watch(reviewerModeProvider)), onSendMessage: (text) => _handleMessageSend(text, selectedModel), onVoiceInput: null, diff --git a/lib/features/navigation/widgets/chats_drawer.dart b/lib/features/navigation/widgets/chats_drawer.dart index 78c95d7..b7ddc77 100644 --- a/lib/features/navigation/widgets/chats_drawer.dart +++ b/lib/features/navigation/widgets/chats_drawer.dart @@ -1406,7 +1406,7 @@ class _ChatsDrawerState extends ConsumerState { ? CupertinoIcons.settings : Icons.settings_rounded, color: theme.iconSecondary, - size: IconSize.small, + size: IconSize.medium, ), ), ], diff --git a/lib/main.dart b/lib/main.dart index 247447b..fab5f1f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -13,7 +13,6 @@ import 'core/persistence/persistence_migrator.dart'; import 'core/persistence/persistence_providers.dart'; import 'core/services/self_signed_certificate_manager.dart'; import 'core/router/app_router.dart'; -import 'shared/widgets/offline_indicator.dart'; import 'features/auth/providers/unified_auth_providers.dart'; import 'core/auth/auth_state_manager.dart'; import 'core/utils/debug_logger.dart'; @@ -218,7 +217,7 @@ class _ConduitAppState extends ConsumerState { maxScaleFactor: 3.0, ), ), - child: OfflineIndicator(child: child ?? const SizedBox.shrink()), + child: child ?? const SizedBox.shrink(), ); }, ), diff --git a/lib/shared/widgets/offline_indicator.dart b/lib/shared/widgets/offline_indicator.dart deleted file mode 100644 index d959af6..0000000 --- a/lib/shared/widgets/offline_indicator.dart +++ /dev/null @@ -1,269 +0,0 @@ -import 'dart:io' show Platform; - -import 'package:flutter/material.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; -import 'package:flutter_animate/flutter_animate.dart'; - -import '../../core/services/connectivity_service.dart'; -import '../../core/providers/app_providers.dart'; -import '../theme/theme_extensions.dart'; -import 'package:conduit/l10n/app_localizations.dart'; - -part 'offline_indicator.g.dart'; - -class OfflineIndicator extends ConsumerWidget { - final Widget child; - - const OfflineIndicator({super.key, required this.child}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final connectivityStatus = ref.watch(connectivityStatusProvider); - final socketConnection = ref.watch(socketConnectionStreamProvider); - final wasOffline = ref.watch(_wasOfflineProvider); - final socketOffline = socketConnection.maybeWhen( - data: (state) => state == SocketConnectionState.disconnected, - orElse: () => false, - ); - - final overlay = () { - if ((connectivityStatus == ConnectivityStatus.offline || socketOffline) && - !wasOffline) { - return const SizedBox.shrink(); - } - if (wasOffline) { - return const _BackOnlineToast(); - } - return const SizedBox.shrink(); - }(); - - return Stack(children: [child, overlay]); - } -} - -// Tracks if the app was recently offline to enable a one-shot back-online toast -@Riverpod(keepAlive: true) -class _WasOffline extends _$WasOffline { - @override - bool build() { - // Initialize based on current connectivity (assume online until proven otherwise) - ref.listen(connectivityStatusProvider, ( - prev, - next, - ) { - if (next == ConnectivityStatus.offline) { - state = true; // mark that we have been offline - } else if (next == ConnectivityStatus.online && state) { - // After we emit the toast once, clear flag shortly after - Future.microtask(() => state = false); - } - }); - return false; - } -} - -class _BackOnlineToast extends StatelessWidget { - const _BackOnlineToast(); - - @override - Widget build(BuildContext context) { - return Positioned( - top: kToolbarHeight + 8, - left: 0, - right: 0, - child: SafeArea( - bottom: false, - child: Semantics( - container: true, - liveRegion: true, - label: AppLocalizations.of(context)!.checkConnection, - child: Align( - alignment: Alignment.topCenter, - child: - Container( - margin: const EdgeInsets.symmetric( - horizontal: Spacing.md, - ), - padding: const EdgeInsets.symmetric( - horizontal: Spacing.md, - vertical: Spacing.xs, - ), - decoration: BoxDecoration( - color: context.conduitTheme.success, - borderRadius: BorderRadius.circular( - AppBorderRadius.round, - ), - boxShadow: ConduitShadows.low(context), - ), - child: Text( - // Reuse existing l10n; otherwise add a dedicated "Back online" key later - AppLocalizations.of(context)!.loadingContent, - style: TextStyle( - color: context.conduitTheme.textInverse, - fontSize: AppTypography.labelLarge, - fontWeight: FontWeight.w600, - ), - ), - ) - .animate(onPlay: (c) => c.forward()) - .fadeIn(duration: const Duration(milliseconds: 200)) - .then(delay: const Duration(milliseconds: 1200)) - .fadeOut(duration: const Duration(milliseconds: 250)), - ), - ), - ), - ); - } -} - -// Inline offline indicator for specific features -class InlineOfflineIndicator extends ConsumerWidget { - final String message; - final IconData? icon; - final Color? backgroundColor; - - const InlineOfflineIndicator({ - super.key, - this.message = '', - this.icon, - this.backgroundColor, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final isOnline = ref.watch(isOnlineProvider); - - if (isOnline) { - 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: surfaceColor, - borderRadius: BorderRadius.circular(AppBorderRadius.md), - border: Border.all( - color: theme.warning.withValues(alpha: borderAlpha), - width: BorderWidth.regular, - ), - ), - child: Row( - children: [ - Icon( - icon ?? - (Platform.isIOS ? CupertinoIcons.wifi_slash : Icons.wifi_off), - color: theme.warning, - size: Spacing.lg, - ), - const SizedBox(width: Spacing.xs), - Expanded( - child: Text( - message.isNotEmpty - ? message - : AppLocalizations.of(context)!.featureRequiresInternet, - style: TextStyle( - color: theme.warning, - fontSize: AppTypography.labelLarge, - fontWeight: FontWeight.w500, - ), - ), - ), - ], - ), - ).animate().fadeIn(duration: const Duration(milliseconds: 300)); - } -} - -// Offline-aware button that disables when offline -class OfflineAwareButton extends ConsumerWidget { - final VoidCallback? onPressed; - final Widget child; - final bool requiresConnection; - final String? offlineTooltip; - - const OfflineAwareButton({ - super.key, - required this.onPressed, - required this.child, - this.requiresConnection = true, - this.offlineTooltip, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final isOnline = ref.watch(isOnlineProvider); - final enabled = !requiresConnection || isOnline; - - return Tooltip( - message: !enabled - ? (offlineTooltip ?? - AppLocalizations.of(context)!.featureRequiresInternet) - : '', - child: FilledButton(onPressed: enabled ? onPressed : null, child: child), - ); - } -} - -// Chat-specific offline indicator -class ChatOfflineOverlay extends ConsumerWidget { - const ChatOfflineOverlay({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final isOnline = ref.watch(isOnlineProvider); - - if (isOnline) { - 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: surfaceColor, - border: Border( - top: BorderSide( - color: theme.warning.withValues(alpha: borderAlpha), - width: BorderWidth.regular, - ), - ), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - Platform.isIOS ? CupertinoIcons.wifi_slash : Icons.wifi_off, - color: theme.warning, - size: Spacing.md, - ), - const SizedBox(width: Spacing.sm), - Text( - AppLocalizations.of(context)!.messagesWillSendWhenOnline, - style: TextStyle( - color: theme.warning, - fontSize: AppTypography.bodySmall, - fontWeight: FontWeight.w500, - ), - ), - ], - ), - ).animate().fadeIn(duration: const Duration(milliseconds: 300)); - } -}