diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e02b843..bbc60040 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ - **Branding**: Changed idle screen title from "Search Music" to "SpotiFLAC" - **About Page Redesign**: New Material Expressive 3 grouped layout with app header, contributors section with GitHub avatars, and organized links +### Fixed +- **Play Button Flash**: Fixed play button briefly showing red error icon on app start (now uses optimistic rendering) + ### Performance - **Optimized State Management**: Use `.select()` for Riverpod providers to prevent unnecessary widget rebuilds - **List Keys**: Added keys to all list builders for efficient list updates and reordering diff --git a/lib/screens/queue_tab.dart b/lib/screens/queue_tab.dart index bada1730..46537f03 100644 --- a/lib/screens/queue_tab.dart +++ b/lib/screens/queue_tab.dart @@ -16,27 +16,41 @@ class QueueTab extends ConsumerStatefulWidget { class _QueueTabState extends ConsumerState { final Map _fileExistsCache = {}; + final Set _pendingChecks = {}; // Track pending async checks static const int _maxCacheSize = 500; // Limit cache size to prevent memory leak + /// Check if file exists - returns true optimistically while checking + /// This prevents the "red flash" on app start bool _checkFileExists(String? filePath) { if (filePath == null) return false; + + // If already cached, return cached value if (_fileExistsCache.containsKey(filePath)) { return _fileExistsCache[filePath]!; } + // If check is pending, return true optimistically (assume file exists) + if (_pendingChecks.contains(filePath)) { + return true; + } + // Limit cache size - remove oldest entry if full if (_fileExistsCache.length >= _maxCacheSize) { _fileExistsCache.remove(_fileExistsCache.keys.first); } + // Mark as pending and start async check + _pendingChecks.add(filePath); Future.microtask(() async { final exists = await File(filePath).exists(); + _pendingChecks.remove(filePath); if (mounted && _fileExistsCache[filePath] != exists) { setState(() => _fileExistsCache[filePath] = exists); } }); - _fileExistsCache[filePath] = false; - return false; + + // Return true optimistically while checking + return true; } Future _openFile(String filePath) async {