From 3313239b4b671e4568cdc6d2d349ca23b24788ec Mon Sep 17 00:00:00 2001 From: edde746 <86283021+edde746@users.noreply.github.com> Date: Sat, 13 Dec 2025 21:14:52 +0100 Subject: [PATCH] fix: sometimes starting on downloads in online mode --- lib/main.dart | 8 +++-- lib/screens/main_screen.dart | 61 ++++++++++++++++++++++++++++++++++-- 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index da52fbd4..64964a9e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -164,10 +164,14 @@ class _MainAppState extends State with WidgetsBindingObserver { ChangeNotifierProvider(create: (context) => ServerStateProvider()), // Offline mode provider - depends on MultiServerProvider ChangeNotifierProxyProvider( - create: (_) => OfflineModeProvider(_serverManager), + create: (_) { + final provider = OfflineModeProvider(_serverManager); + provider.initialize(); // Initialize immediately so statusStream listener is ready + return provider; + }, update: (_, multiServerProvider, previous) { final provider = previous ?? OfflineModeProvider(_serverManager); - provider.initialize(); + provider.initialize(); // Idempotent - safe to call again return provider; }, ), diff --git a/lib/screens/main_screen.dart b/lib/screens/main_screen.dart index 18747e4a..1a1552d1 100644 --- a/lib/screens/main_screen.dart +++ b/lib/screens/main_screen.dart @@ -65,6 +65,12 @@ class _MainScreenState extends State with RouteAware { /// Whether the app is in offline mode (no server connection) bool _isOffline = false; + /// Last selected online tab (restored when coming back online after an offline fallback) + NavigationTabId? _lastOnlineTabId; + + /// Whether we auto-switched to Downloads because the previous tab was unavailable offline + bool _autoSwitchedToDownloads = false; + OfflineModeProvider? _offlineModeProvider; late List _screens; @@ -93,6 +99,8 @@ class _MainScreenState extends State with RouteAware { // In offline mode: visual index 0 = Downloads (screen 3), 1 = Settings (screen 4) // In online mode: indices match directly _currentIndex = _isOffline ? 0 : 0; + _lastOnlineTabId = _isOffline ? null : NavigationTabId.discover; + _autoSwitchedToDownloads = _isOffline; _screens = _buildScreens(_isOffline); @@ -119,12 +127,15 @@ class _MainScreenState extends State with RouteAware { super.didChangeDependencies(); // Listen for offline/online transitions to refresh navigation & screens + // Note: We don't call _handleOfflineStatusChanged() immediately because + // widget.isOfflineMode (from SetupScreen navigation) is authoritative for + // initial state. The provider may not yet have received the server status + // update due to initialization timing. The listener handles runtime changes. final provider = context.read(); if (provider != null && provider != _offlineModeProvider) { _offlineModeProvider?.removeListener(_handleOfflineStatusChanged); _offlineModeProvider = provider; _offlineModeProvider!.addListener(_handleOfflineStatusChanged); - _handleOfflineStatusChanged(); } routeObserver.subscribe(this, ModalRoute.of(context) as PageRoute); @@ -187,12 +198,41 @@ class _MainScreenState extends State with RouteAware { if (newOffline == _isOffline) return; + final previousTabId = _tabIdForIndex(_isOffline, _currentIndex); final wasOffline = _isOffline; setState(() { _isOffline = newOffline; _screens = _buildScreens(_isOffline); _selectedLibraryGlobalKey = _isOffline ? null : _selectedLibraryGlobalKey; - _currentIndex = _normalizeIndexForMode(_currentIndex, wasOffline, _isOffline); + + if (_isOffline) { + // Remember the online tab so we can restore it when reconnecting. + if (!wasOffline) { + _lastOnlineTabId = previousTabId; + } + + _currentIndex = + _normalizeIndexForMode(_currentIndex, wasOffline, _isOffline); + + // Track if we auto-switched to Downloads because the previous tab was unavailable. + _autoSwitchedToDownloads = + previousTabId != NavigationTabId.downloads && + _tabIdForIndex(true, _currentIndex) == NavigationTabId.downloads; + } else { + // Coming back online: restore the last online tab if we forced a switch to Downloads. + if (_autoSwitchedToDownloads) { + final restoredTab = _lastOnlineTabId ?? NavigationTabId.discover; + final restoredIndex = NavigationTab.indexFor( + restoredTab, + isOffline: _isOffline, + ); + _currentIndex = restoredIndex >= 0 ? restoredIndex : 0; + } else { + _currentIndex = + _normalizeIndexForMode(_currentIndex, wasOffline, _isOffline); + } + _autoSwitchedToDownloads = false; + } }); // Refresh sidebar focus after rebuilding navigation @@ -343,6 +383,12 @@ class _MainScreenState extends State with RouteAware { final previousIndex = _currentIndex; setState(() { _currentIndex = index; + if (!_isOffline) { + _lastOnlineTabId = _tabIdForIndex(false, index); + } else if (previousIndex != index) { + // User made an explicit offline selection, so don't auto-restore later. + _autoSwitchedToDownloads = false; + } }); // Skip screen-specific logic in offline mode (only Downloads and Settings available) @@ -371,6 +417,9 @@ class _MainScreenState extends State with RouteAware { setState(() { _selectedLibraryGlobalKey = libraryGlobalKey; _currentIndex = 1; // Switch to Libraries tab + if (!_isOffline) { + _lastOnlineTabId = NavigationTabId.libraries; + } }); // Tell LibrariesScreen to load this library if (_librariesKey.currentState case final LibraryLoadable loadable) { @@ -386,6 +435,14 @@ class _MainScreenState extends State with RouteAware { return NavigationTab.getVisibleTabs(isOffline: isOffline); } + /// Get the tab ID for a given index, clamping to the available range. + NavigationTabId _tabIdForIndex(bool isOffline, int index) { + final tabs = _getVisibleTabs(isOffline); + if (tabs.isEmpty) return NavigationTabId.discover; + final safeIndex = index.clamp(0, tabs.length - 1).toInt(); + return tabs[safeIndex].id; + } + /// Build navigation destinations for bottom navigation bar. List _buildNavDestinations(bool isOffline) { return _getVisibleTabs(isOffline).map((tab) => tab.toDestination()).toList();